오늘은 스마트 포인터와 벡터,리스트,언오더드맵에 대해 배웠다.
이것들에 대해 정리한다.
스마트 포인터
#include<memory> 를 해주어야 한다.
unique_ptr, shared_ptr, weak_ptr 3개가 있다.
하나하나 파보자.
unique_ptr
개념
유니크 ptr
참조자를 1개만 허용해준다.
스마트포인터로 참조자를 1개 만들고나서 , 다른 스마트포인터로 앞의 참조자가 참조하려는 인스턴스를 참조하려고하면 허용하지 않는다.
1개만 참조를 해야하는 경우에 사용한다.
생성하기
int main()
{
unique_ptr<Animal> p = make_unique<Animal>(10); //Animal이라는 클래스를 생성함
p.get()->YourMaxAge();
p->YourMaxAge();
}
유니크 ptr로 1일차에 만들었던 Animal이라는 클래스를 생성 해주었다.
make_unique<T> 로 생성한다.
인스턴스에 접근하는법은
p.get() -> 함수or변수;
p -> 함수or변수;
둘 중 아무거나 상관없다.
당연히 후자가 편리하다.
실행을 해보면 delete를 해주지 않아도 알아서 소멸자가 나오는 것을 볼 수 있다. (이래서 스마트?)
Animal* p = make_unique<Animal>(10).get();
이런식으로도 생성 가능하다. 다만 unique_ptr로 생성한것을 일반 포인터로 받았기 때문에 소유권 이전에 문제가 있다.
참조 옮기기 (소유권 이전시키기)
unique_ptr<Animal> p = make_unique<Animal>(10); //Animal이라는 클래스를 생성함
p.get()->YourMaxAge();
p->YourMaxAge();
unique_ptr<Animal> p2 = p; //허용하지 않음
unique_ptr<Animal> p2 = move(p);
참조자를 1개만 인정하기 때문에 p2가 그대로 p를 참조하는 것을 허용하지는 않는다.
대신 move()를 이용해 참조자를 옮기는 것은 가능하다.
int main()
{
unique_ptr<Animal> p = make_unique<Animal>(10); //Animal이라는 클래스를 생성함
unique_ptr<Animal> p2 = move(p);
p2->YourMaxAge();
}
p에서 p2로 참조자를 옮기고 p2에서 함수를 실행해보면 아주 잘 작동한다.
Animal* p2 = move(p).get(); // 참조하는 애의 주소를 리턴해줌 // 소유주를 옮기는게 문제가 됨
get() 은 참조하는 주소를 리턴해준다.
위와 같은 코드로도 참조자를 변경 해줄 수 있지만 이 역시 다시 다른 참조자로 옮기는 것이 문제가 된다.
(unique_ptr이 아닌 포인터 이기 때문에)
shared_ptr
우리가 평소에 사용하던 포인터와 비슷하다.
shared_ptr로 참조자를 만들면 레퍼런스 카운터라는것을 만든다.
참조하는 개수 만큼 레퍼런스 카운터를 가지고 있다가 참조가 사라지면 레퍼런스 카운터가 감소한다.
참조하는 수가 0이 되면, 인스턴스도 자동으로 삭제를 해준다.(스마트 하다)
shared_ptr의 생성
int main()
{
shared_ptr<Animal> p = make_shared<Animal>(10); //Animal이라는 클래스를 생성함
Animal* p2 = p.get();
cout << "p의 주소 : " << p << endl;
cout << "p2의 주소 : " << p2 << endl;
p->YourMaxAge();
p2->YourMaxAge();
}
make_shared로 생성 할 수 있다.
unique_ptr 처럼 참조자가 1개만 되는것이 아니기 때문에 일반 포인터 p2가 shared_ptr로 생성한 p의 주소를 참조 하게 해도 문제가 없다
값 , 주소가 모두 같은 것을 볼 수 있다.
그리고 역시 delete가 없음에도 불구하고 소멸이 잘 이루어지며 오류가 없는 것을 확인 할 수 있다.
weak_ptr
위에 shared_ptr로 참조하면 레퍼런스 카운터가 늘어나지만, Weak_ptr로 참조하면 레퍼런스 카운터가 증가하지 않음.
반대로 참조를 해제해도 레퍼런스 카운터가 감소하지 않음(간접 참조)
위의 예를 실험하기 위해 코드를 입력한다.
int main()
{
weak_ptr<Animal> wp;
{
shared_ptr<Animal> p = make_shared<Animal>(10); //Animal이라는 클래스를 생성함
wp = p;
cout << "p 삭제" << endl;
}
cout << "wp 삭제" << endl;
}
shared_ptr은 레퍼런스 카운트가 0이 됐을때 할당이 해제 된다.
위의 코드에서 weak_ptr은 메인 함수에 존재하고
shared_ptr은 저 소괄호 안에 존재한다.
1. shared_ptr로 클래스를 생성한다. (레퍼런스 카운트 1)
2.weak_ptr이 p를 참조하게 한다. (여전히 레퍼런스 카운트 1)
3. p 삭제라는 글이 출력되고 나서 shared ptr은 소멸되기 때문에 레퍼런스 카운트가 0이 되어서 메모리 할당이 해제되고 소멸자를 호출한다.
4. 그 다음에 wp 삭제가 출력된다.
위 설명과 같이 p삭제가 출력 되고나서 소멸자가 호출되고 wp삭제가 출력 됐다.
weak_ptr의 참조는 레퍼런스 카운트에 영향을 주지 못한다.
'프로그래밍 공부 > C++ 프로그래밍' 카테고리의 다른 글
Direct X 4일차💻 <WINAPI> #2 (0) | 2022.06.19 |
---|---|
WINAPI 추가정리 (0) | 2022.06.19 |
Direct X 3일차💻 <WINAPI> #1 (0) | 2022.06.19 |
Direct X 2일차💻 C++의 동적 배열 (0) | 2022.06.15 |
direct X 수업 1일차💻 C++의 클래스 / 그 외 (0) | 2022.06.15 |
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!