Smart Pointer

스마트 포인터는 포인터 문법에 소유권 정책을 더한다

unique_ptr, shared_ptr, weak_ptr은 delete를 자동화하는 정도가 아니라 누가 객체를 소유하는지 타입으로 드러낸다. 공유가 필요한 순간부터 비용과 순환 참조를 함께 본다.

01

소유자를 한 명으로 시작한다

대부분은 unique_ptr 또는 값 멤버로 표현할 수 있다. shared_ptr은 실제 공유 수명이 있을 때만 쓴다.

02

전달 의미를 타입에 담는다

함수 인자로 unique_ptr을 값으로 받으면 소유권 이전, T*나 T&는 관찰을 뜻하게 둔다.

03

순환을 끊는다

shared_ptr끼리 서로 잡으면 카운트가 0이 되지 않으므로 한쪽은 weak_ptr로 만든다.

unique_ptr
독점 소유 복사 불가, 이동 가능이라 소유권 이전이 코드에 드러난다.
make_unique를 기본으로 쓴다.
shared_ptr
공유 수명 참조 카운트 증가와 원자적 비용이 붙을 수 있다.
기본 선택지로 쓰면 소유권이 흐려진다.
weak_ptr
비소유 관찰 lock으로 살아 있는 동안만 shared_ptr을 얻는다.
캐시와 부모 참조의 순환 소유를 피한다.
raw pointer
소유권 없음 nullable 관찰이나 C API 경계에서 제한적으로 쓴다.
delete 책임을 갖게 하지 않는다.

shared 남용 · 순환 · 전달 점검

shared 남용 실제 공유 수명 없이 편해서 shared_ptr을 쓰고 있지 않은가.
순환 양방향 그래프나 parent-child 구조에서 shared_ptr cycle이 생기지 않는가.
전달 함수 시그니처만 보고 소유권 이전인지 관찰인지 알 수 있는가.

소유권 이전

std::unique_ptr<Node> make_node(std::string name) {
    return std::make_unique<Node>(std::move(name));
}

void attach(std::unique_ptr<Node> child); // 호출 후 child 소유권 이전