2010-11-21 3 views
12

TR1에는 shared_ptr, weak_ptr, scoped_ptr 및 unique_ptr 외가 도입되었습니다.C++에서 다양한 스마트 포인터 간의 변환에 대한 규칙은 무엇입니까

이러한 유형 간의 다양한 변환/유형 홍보 규칙을 알고 싶습니다.

예를 들어 scoped_ptr이 shared_ptr에 할당되면 어떻게됩니까? 그러한 전환이 가능합니까/의미 있고 그러한 전환에 대한 사용 사례가 있습니까?

(테이블이 specifiction에 있습니까?)

답변

12

첫째, 귀하의 질문에 대한 수정의 몇 :

  • scoped_ptr 부스트의 일부이며, C 중 하나에 포함되지 않습니다 ++ TR1 또는 C++ 0x (C++에서는 scoped_ptr이 전통적으로 사용 된 경우 0x unique_ptr을 사용할 수 있습니다).

  • unique_ptr은 C++ TR1의 일부가 아닙니다. 이것은 C++ 0x의 일부입니다 (rvalue 참조와 이동 의미론에 의존하기 때문에 C++ 0x에서만 사용 가능합니다).

은 귀하의 질문에 대답하려면 : shared_ptrweak_ptr이 손에 손을 이동합니다. shared_ptr이 소유 한 객체는 weak_ptr으로 참조 할 수도 있습니다. 그들은 보완 적입니다.

unique_ptr은 자신이 관리하는 개체의 단독 소유권을가집니다. 아무도 그 객체의 소유권을 가질 수 없습니다. 이는 shared_ptr의 소유권 의미와 반대입니다. unique_ptr을 사용하면 고유 한 소유권이 공유되지 않습니다. shared_ptr과 (와) 공유 한 고유하지 않은 소유권이 있습니다.

shared_ptrunique_ptr에서 구성 할 수 있습니다. 이렇게하면 unique_ptr 개체의 소유권이 손실됩니다. 이는 항상 주어진 unique_ptr이 항상 개체의 유일한 소유자이므로 항상 소유권을 해제 할 수 있다는 것을 알고 있기 때문에 효과적입니다.

개체가 shared_ptr에 의해 소유되면 지정된 shared_ptr이 개체의 유일한 소유자라는 보장이 없기 때문에 개체의 소유권을 해제 할 수 없습니다.

+0

@sonicoder :'scoped_ptr'가 복사 할 수없는 것처럼'unique_ptr'도 복사 할 수 없습니다. 'unique_ptr'와'scoped_ptr'의 의미는'unique_ptr'이 이동 될 수 있기 때문에 분명하지 않습니다. 그러나 그것들은 유사하고'scoped_ptr'를 사용하는 경우는 거의 없지만'unique_ptr'는 바람직하지 않을 것입니다. –

2
  1. scoped_ptr AFAIK은 TR1의 일부가 아닙니다 (잘못된 경우 나 수정하십시오). 일반적으로 boostscoped_ptr은 소유권을 전혀 이전 할 수 없습니다. 포인터를 할당하면 해제 할 수 없습니다.
  2. unique_ptrstd::move만을 사용하여 소유권을 이전 할 수 있으므로 소유권도 이전하지 않습니다.
  3. shared_ptr은 다른 포인터와 공유 할 수 있으므로 소유권을 해제 할 수 없습니다. weak_ptr으로 변환 할 수 있습니다. weak_ptr에서 개체를 변환하려고하면 개체가 놓이게됩니다.
  4. weak_ptrshared_ptr에서 생성 할 수 있으며 shared_ptr으로 변환하면 더 이상 존재하지 않을 경우 throw 될 수 있습니다.
3

을 감안할 때 두 개의 클래스 AB (스마트 포인터 타입이 될 수 있음), A를 입력 할 유형 B의 인스턴스를 변환하는 네 가지 방법이 있습니다 :

  • A가 액세스 기지 (예 : BA에서 공개적으로 파생 됨) 변환은 참조 또는 포인터의 유형을 슬라이스하거나 간단하게 조정할 수 있습니다. (의도적 인 경고)

  • A에는 B을 취하는 액세스 가능한 생성자가 있습니다.

  • B에는 A을 생성하는 액세스 가능한 변환 연산자가 있습니다.

  • B을 사용하고 A을 생성하는 함수가 있습니다.이 함수를 호출하는 것입니다.

상속으로 인해 잘못된 변환이 허용되므로 스마트 포인터 상속은 변환을 용이하게하기 위해 사용되지 않습니다. 그러므로 위의 파업. 예를 들어 SmartPtr<Derived>SmartPtr<Base>에서 공개적으로 상속 된 경우 SmartPtr<Base>& spBase = spDerived;을 수행 한 다음 spBase = spOtherDerived, 이는 다소 문제가 될 것입니다 ... 적절하게 높은 수준의 추상화에서 이것은 기본적으로 포인터 변환을 위해 const과 동일한 문제입니다. FAQ 항목 18.17 "Why am I getting an error converting a Foo** → Foo const**?"을 참조하십시오.

따라서 스마트 포인터 변환은 일반적으로 마지막 세 개의 글 머리 기호, 즉 생성자, 변환 연산자 및 명명 된 변환 함수를 통해 표현됩니다. 하나의 개체에 대한

  • std::unique_ptr :

    기본적으로 사용되지 않는 auto_ptr 무시 C + +0 세 스마트 포인터가 있습니다.

  • std::unique_ptr 어레이의 경우.

  • std::shared_ptr 단일 개체의 경우. 이전 auto_ptr가했고, 마찬가지로

unique_ptr소유권 이전을 표현한다. 그러나 auto_ptr은 배열을 지원하지 않았습니다. unique_ptr 않습니다 및 가능한 전환에 영향을줍니다.

단일 개체의 경우 unique_ptr은 생성자를 통해 해당 원시 포인터가 수행하는 변환을 지원합니다. 그것은 다른 형식의 unique_ptr을 취하는 템플릿 생성자를가집니다. 예 : C++ 0x 초안 N3126 §20.9.10.2.

그러나 원시 포인터처럼 위험 할 수있는 배열의 경우! 따라서 배열의 경우 unique_ptr이 아니며 쿠폰/파생 변환을 제공합니다. 예 : C++ 0x 초안 N3126 §20.9.10.3.shared_ptr는 공유 소유권을 표현하면서 unique_ptr 이후

소유권 전달 표현shared_ptr에서 unique_ptr에 안전한 일반 변환있을 수 없다. 그러나 다른 방법으로 Boost shared_ptr에는 생성자가 auto_ptr이고 C++ 0xshared_ptr은이 값을 유지하며 자연스럽게 unique_ptr을 생성하는 생성자를 추가합니다. C++ 0x 초안 N3126 §20.9.11.2/1을 참조하십시오.

shared_ptr은 개념적으로 "캐스트"를 구현하는 무료 함수 및 생성자를 통해 기본/파생 변환을 제공합니다. 기본적으로 이것은 shared_ptr이 클래스 유형 객체의 배열에 직접 사용하는 것은 매우 위험하다는 것을 의미합니다. 그 용도로 포장하십시오.

위에서 설명한대로 shared_ptr에서 unique_ptr으로의 변환은 일반적인 작업으로 지원되지 않습니다. 공유 소유권이 소유권 이전과 직접적으로 호환되지 않기 때문입니다. 그러나 합병증을 무시하고 있습니다. 스레드 안전성 shared_ptr::unique단일 소유자 (예 : 인스턴스)이 있는지 여부를 알려주고, 초기 shared_ptr이 어떻게 생성되었는지에 대한 필수 지식이있는 경우 무료 함수 get_deleter을 사용하여 deleter 기능을 수행하고 일부 낮은 수준의 속임수를 수행합니다. 내가 여기서 말하고있는 것을 완전히 이해한다면, 좋아, 좋아. 그렇지 않다면 더 자세한 정보를 제공하지 않는 것이 가장 좋습니다. 이는 매우 특별한 경우이며 최대한주의를 기울여야하며 실제로 당신이하는 일을 잘 알고 있어야합니다. ™. ;-)

음, 그게 전부입니다. weak_ptr은 단지 shared_ptr 기능의 일부이므로 논의하지 않습니다. 그러나 위의 내용이 당신이 요구하는 바입니다.