결론
• unique_ptr은 독점소유권 의미론을 가진 자
원의 관리를 위한, 작고 빠른 이동전용 똑똑한
포인터이다.
• 기본적으로 자원 파괴는 delete를 통해 일어
나나, 커스텀 삭제자를 지정할 수 도 있다. 상
태 있는 삭제자나 함수 포인터를 사용하면
unique_ptr 객체의 크기가 커진다
제어블록 생성 규칙
•std::make_shared는 항상 제어블록을
생성한다
shared_ptr을 가리키는 객체를 새로
생성하기 때문에 그 객체에 대한 제어블록이
이미 존재할 가능성이 없다
• shared_ptr이나 weak_ptr로부터
shared_ptr을 생성하면 기존 포인터에서
가지고 있는 제어블록을 참고한다
32.
제어블록 생성 규칙
•고유 소유권 포인터(unique_ptr, auto_ptr)
로부터 shared_ptr 객체를 생성하면
제어블록이 생성된다
- 고유 소유권은 제어블록을 사용하지 않기
때문에 해당 객체에 대한 제어블록이 없다고
보장한다
- 고유 소유권 포인터는 shared_ptr로 이동
하면 해당 객체에 대한 권한을 상실한다
33.
제어블록 생성 규칙
•생 포인터로 shared_ptr을 생성하면 제어블
록이 생성된다
auto praw = new int(11);
shared_ptr<int> spwFromRaw1(praw);
shared_ptr<int> spwFromRaw2(praw);
// 미정의 행동!
shared_ptr<int> spwGood(new int(11));
// 미정의 행동 방지
this 포인터
class Widget;
vector<shared_ptr<Widget>>processWidgets;
class Widget : public enable_shared_from_this<Widget>
{
public:
void process()
{
processWidgets.emplace_back(shared_from_this());
}
};
// Curiously Recurring Template Pattern
// 문제 해결?
36.
this 포인터
class Widget;
vector<shared_ptr<Widget>>processWidgets;
class Widget : public enable_shared_from_this<Widget>
{
public:
template<typename ... Ts>
static shared_ptr<Widget> Create(void)
{
return shared_ptr<Widget>(new Widget());
}
void process()
{
processWidgets.emplace_back(shared_from_this());
}
private:
Widget() {};
};
37.
비싼 비용?
• make_shared로shared_ptr을 생성하면
제어 블록할당 비용은 무료다
• 제어블록에 있는 가상 함수는 많이 호출되지
않는다
• 원자 연산은 기계어 명령에 대응되기 때문에
비용이 그렇게 크지 않다
• 그래도 부담스럽다면 unique_ptr로 선언한
뒤 업그레이드 하면 된다
38.
그 외
• 단일객체 관리를 염두에 두고 설계되었기
때문에 operator[]를 제공하지 않는다
39.
결론
• shared_ptr는 임의의공유 자원의 수명을
편리하게 관리할 수 있는 수단을 제공한다
• 대체로 shared_ptr객체의 크기는
unique_ptr의 두 배이며, 제어 블록에
관련된 추가 부담을 유발하며,
원자적 참조 횟수 조작을 요구한다.
40.
결론
• 자원은 기본적으로delete를 통해 파괴되나
커스텀 삭제자도 지원한다. 삭제자의 형식은
shared_ptr의 형식에 아무런 영향도 미치지
않는다
• 생 포인터의 형식의 변수로부터
shared_ptr을 생성하는 일은 피해야 한다