std::weak_ptr
및 std::owner_less
과 관련 컨테이너 std::set
및 std::map
에 대한 사용과 관련하여 많은 질문이 오늘있었습니다. 약한 포인터가 만료되면 정의되지 않은 동작이므로 std::set
에있는 weak_ptr
을 사용하면 올바르지 않다고하는 많은 게시물이 있습니다. 이 올바른지?std :: map에서 weak_ptr을 사용하는 것이 안전합니까?
답변
이유 중 하나는 std::owner_less
이 주문을 제공하고 약한 포인터 만료시 안전을 보장하는 것입니다. 내 로직
먼저 std::owner_less
연산자의 정의()
operator()
의해 정의 동치 관계하에 25.4항에 엄격한 약한 순서를 정의
!operator()(a, b) && !operator()(b, a)
두shared_ptr
이고 또는weak_ptr
인스턴스는 소유권을 공유하거나 둘 다 비어있는 경우에만 동등합니다.
두 경우 그들은 실제 용어는 동일한 참조 횟수 객체를 공유하는 것을 의미 같은 객체를 공유
- 이다.
- 둘 다 비어 있습니다.
이제 혼란이 두 번째 임기를 넘었다 고 생각합니다. 핵심은 표준에서 "비어 있음"은 weak_ptr
이 모든 개체와 소유권을 공유하지 않는다는 것을 의미합니다. 또, 표준 상태
constexpr weak_ptr() noexcept;
효과
는 : 빈
weak_ptr
오브젝트를 구축합니다.
사후 조건 :use_count() == 0
.template<class Y> weak_ptr(const shared_ptr<Y>& r) noexcept;
template<class Y> weak_ptr(const weak_ptr<Y>& r) noexcept;
weak_ptr(const weak_ptr& r) noexcept;
이 필요합니다
Y*
이
T*
에 암시 적으로 변환하지 않는 한 두 번째와 세 번째 생성자는 오버로드 확인에 참여하지 않는다.
효과 : r
이 비어있는 경우 빈 weak_ptr
개체를 구성합니다. 그렇지 않은 경우 소유권을 공유하는 weak_ptr
개체를 r
으로 구성하고 r
에 저장된 포인터 복사본을 저장합니다.
사후 조건 : use_count() == r.use_count()
.
스왑 두 weak_ptr
(S)의 교환 상태를 정의하고, 할당 스왑 함께 상기 생성자를 사용하여 정의된다.
여기에서 중요한 점은 비어있는 weak_ptr
을 생성하는 유일한 방법은 기본 구성이거나 이전에 비어있는 weak_ptr
또는 shared_ptr
에서 복사/이동/할당하는 것입니다. 또한 weak_ptr
만료로 빈 weak_ptr
을받을 수 없다는 점에 유의해야합니다. 만료 된 weak_ptr
은 단순히 use_count
이 0입니다. 실질적인 문제하는 shared_ptr
만들 때 std::make_shared
가 사용될 때, 기준 카운트 객체가 shared_ptr
생성자를 사용하여 데이터로부터 분리하거나 동일한 메모리 할당에서 역시 생성 될 것처럼
weak_ptr
이
shared_ptr
으로 구성되면 동일한 제어 구조 및 참조 횟수를 가리 킵니다.
shared_ptr
이 파괴되면 데이터가 파괴 될 수 있지만 소유권을 공유하는
weak_ptr
이 모두 제거 될 때까지 참조 횟수 객체가 유지되어야합니다. 그렇지 않으면
weak_ptr
에 매달린 포인터 참조가 있습니다.
그래서, 함께이 모든 그것만큼 당신이 순서를 수행 할 std::owner_less
을 사용하는 등의 std::map
의 그들이 키로 또는 std::set
에 std::weak_ptr
을 사용하는 것이 안전하다는 것을 의미한다. 위의 내용에 따라 weak_ptr
의 주문은 컨테이너에있는 동안 만료 되더라도 그대로 유지됩니다.
이 답변에 결론을 추가 할 수 있습니까? :) – Drax
@Drax : 물론. 나는 밤늦게이 편지를 썼다. 나는 그런 작은 정보를 놓쳤다. –
멋진, 고마워요. :) – Drax