-
항목20. std::shared_ptr처럼 작동하되 대상을 잃을 수도 있는 포인터가 필요하면 std::weak_ptr을 사용하라Effective Modern C++ 2022. 8. 11. 23:44
std::weak_ptr은 std::shared_ptr처럼 작동하되 소유권 참조 횟수에는 참가하지 않는다. 대상을 잃은 std::waek_ptr은 만료된 상태를 가진다.
if (wpw.expired())... // 만료를 직접 판정할 수 있음미정의 행동이 방지하려면 만료를 직접 판정하고 피지칭 객체에 대한 접근을 돌려주는 연산을 원자적 연산으로 수행하는 것이다.
std::shared_ptr<Widget> spw1 = wpw.lock(); // 만료됐으면 널 배정 auto spw2 = wpw.lock(); std::shared_ptr<Widget> spw3(wpw); // 만료됐으면 예외 발생
주어진 고유 ID에 해당하는 읽기 전용 객체를 가리키는 똑똑한 포인터를 돌려주는 팩터리 함수가 있다고 하자. 호출 결과를 캐싱하고, 더 이상 쓰이지 않는 객체는 캐시에서 삭제한다.
- 캐시에 있는 포인터들은 자신이 대상을 잃었음을 검출할 수 있어야 한다.
- 팩토리 함수가 돌려준 객체를 클라이언트가 다 사용하고 나면 그 객체 는 파괴되며, 그러면 해당 캐시 항목은 대상을 잃게 될 것이기 때문이다.
- 따라서 캐시에 저장할 포인터는 자신이 대상을 잃었음을 감지할 수 있는 포인터, 즉 std::weak_ptr이어야 한다.
- 이는 팩토리 함수의 반환 형식이 반드시 std::shared_ptr이어야 함을 뜻한다.
- std::weak_ptr는 객체의 수명을 std::shared_ptr로 관리하는 경우에만 자신이 대상을 잃었음을 감지할 수 있기 때문이다.
std::shared_ptr<const Widget> fastLoadWidget(WidgetID id) { static std::unoredered_map<WidgetId, std::weak_ptr<const Widget>> cache; auto objPtr = cache[id].lock(); // objPtr는 캐시에 있는 객체를 가리키는 std::shared_ptr // 단 객체가 캐시에 없으면 널 if (!objPtr) // 캐시에 없으면 적재하고 캐시에 저장 { objPtr = loadWidget(id); cache[id] = objPtr; } return objPtr; }- 관찰자 설계 패턴
A --------std::shared_ptr-------> B <-------std::shared_ptr------------C
A와 C가 B의 소유권을 공유하고있다. 이때 B에서 다시 A를 가리키는 포인터가 필요하다고 하자. 그 포인터는 어떤 종류의 포인터이어야 할까?- 생 포인터 : A가 파괴되면 A를 가리키는 생 포인터는 대상을 잃고, 역참조시 미지의 행동이 발생
- std::shared_ptr : A와 B 서로를 가리키는 순환 고리가 생기고 둘 다 파괴하지 못하는 사실상 누수가 발생한다.
- std::weak_ptr : A가 파괴돼도 A를 가리키는 std::weak_ptr포인터는 그 사실을 알 수 있다. 또한 A와 B가 서로를 가리켜도 std::weak_ptr은 참조 횟수에 영향을 주지 않아 A는 파괴가능하다.
물론 트리 구조처럼 자식 노드들은 오직 한 부모만 소유한다. 이런 경우는 보통 std::unique_ptr로 표현하는 것이 최선이다. 자식에서 부모로의 역링크는 생 포인터로 충분하다. 어차피 자식 노드의 수명은 부모의 수명 보다 길 수는 없다.
'Effective Modern C++' 카테고리의 다른 글
항목22. Pimpl 관용구를 사용할 때에는 특수 멤버 함수들을 구현 파일에서 정의하라 (0) 2022.08.16 항목21. new를 직접 사용하는 것보다 std::make_unique와 std::make_shared를 선호하라 (0) 2022.08.11 항목19. 소유권 공유 자원의 관리에는 std__shared_ptr를 사용하라 (0) 2022.08.05 항목18. 소유권 독점 자원 관리는 std__unique_ptr를 사용하라 (0) 2022.08.03 항목17. 특수 멤버 함수들의 자동 작성 조건을 숙지하라. (0) 2022.07.29