shared_ptr 매직 :)
Lidström의 주장은 구조 shared_ptr<Base> p(new Derived);
가 Base에 가상 소멸자를 필요로하지 않는다는 것입니다 .
Armen Tsirunyan : "정말? shared_ptr이 올바르게 정리 될까요?이 경우 어떻게 그 효과를 구현할 수 있는지 보여 주시겠습니까?"
Daniel Lidström : " shared_ptr 는 자체 소멸자를 사용하여 Concrete 인스턴스를 삭제합니다. 이것은 C ++ 커뮤니티 내에서 RAII로 알려져 있습니다. 제 조언은 RAII에 대해 배울 수있는 모든 것을 배우는 것입니다. 사용하면 C ++ 코딩이 훨씬 쉬워 질 것입니다. 모든 상황에서 RAII. "
Armen Tsirunyan : "RAII에 대해 알고 있습니다. 또한 pn이 0에 도달하면 shared_ptr 소멸자가 저장된 px를 삭제할 수 있다는 것도 알고 있습니다. 그러나 px 에에 대한 정적 형식 포인터
Base
와에 대한 동적 형식 포인터 가있는 경우 가상 소멸자가Derived
없는 한Base
이것은 정의되지 않은 동작이 발생합니다. 내가 틀렸다면 수정하십시오. "Daniel Lidström : " shared_ptr 은 정적 유형이 Concrete라는 것을 알고 있습니다. 생성자에 전달했기 때문에 이것을 알고 있습니다! 약간 마술처럼 보이지만 설계 상 매우 훌륭하다고 확신 할 수 있습니다."
그래서 우리를 판단하십시오. 가상 소멸자를 갖기 위해 다형성 클래스를 요구하지 않고 shared_ptr 을 구현하는 것이 어떻게 가능 합니까? 미리 감사드립니다
예, 그런 방식으로 shared_ptr을 구현하는 것이 가능합니다. Boost는 그렇고 C ++ 11 표준도이 동작을 요구합니다. 추가 된 유연성으로 shared_ptr은 단순한 참조 카운터 이상을 관리합니다. 소위 삭제자는 일반적으로 참조 카운터도 포함하는 동일한 메모리 블록에 배치됩니다. 그러나 재미있는 부분은이 삭제 자의 유형이 shared_ptr 유형의 일부가 아니라는 것입니다. 이를 "타입 삭제"라고하며 기본적으로 실제 펑터의 유형을 숨기기 위해 "다형성 함수"boost :: function 또는 std :: function을 구현하는 데 사용되는 것과 동일한 기술입니다. 예제가 작동하도록하려면 템플릿 생성자가 필요합니다.
template<class T>
class shared_ptr
{
public:
...
template<class Y>
explicit shared_ptr(Y* p);
...
};
따라서 이것을 Base 및 Derived 클래스와 함께 사용하면 ...
class Base {};
class Derived : public Base {};
int main() {
shared_ptr<Base> sp (new Derived);
}
... Y = Derived 인 템플릿 생성자는 shared_ptr 객체를 생성하는 데 사용됩니다. 따라서 생성자는 적절한 삭제 자 개체와 참조 카운터를 만들고이 제어 블록에 대한 포인터를 데이터 멤버로 저장할 수 있습니다. 참조 카운터가 0에 도달하면 이전에 생성되고 파생 인식 삭제 기가 개체를 처리하는 데 사용됩니다.
C ++ 11 표준에는이 생성자 (20.7.2.2.1)에 대해 다음과 같은 내용이 있습니다.
필요 :
p
로 변환 할 수 있어야합니다T*
.Y
완전한 유형이어야합니다. 표현delete p
은 잘 형성되어야하고 잘 정의 된 행동을 가져야하며 예외를 던지지 않아야합니다.효과 : 포인터 를 소유 한
shared_ptr
개체 를 생성 합니다 .p
…
그리고 소멸자의 경우 (20.7.2.2.2) :
효과 :
*this
이 비어 있거나 다른shared_ptr
인스턴스 (use_count() > 1
) 와 소유권을 공유하는 경우 부작용이 없습니다. 그렇지 않으면,*this
객체 소유p
하고 Deleter가를d
,d(p)
이라고합니다. 그렇지 않은 경우는*this
포인터를 소유p
하고,delete p
라고합니다.
(굵은 글꼴을 사용한 강조는 내 것입니다).
shared_ptr을 생성 할 때 그것은 저장 Deleter가의 자체 내부 개체. 이 개체는 shared_ptr이 지적 된 리소스를 해제하려고 할 때 호출됩니다. 생성 시점에서 리소스를 파괴하는 방법을 알고 있으므로 불완전한 유형으로 shared_ptr을 사용할 수 있습니다. shared_ptr을 만든 사람은 거기에 올바른 삭제자를 저장했습니다.
예를 들어 사용자 지정 삭제자를 만들 수 있습니다.
void DeleteDerived(Derived* d) { delete d; } // EDIT: no conversion needed.
shared_ptr<Base> p(new Derived, DeleteDerived);
p는 뾰족한 객체를 파괴하기 위해 DeleteDerived를 호출합니다. 구현은이를 자동으로 수행합니다.
간단히,
shared_ptr
Base의 소멸자가 아닌 지정된 객체의 소멸자를 항상 사용하는 생성자에 의해 생성되는 특수 삭제 기능을 사용합니다. 이것은 템플릿 메타 프로그래밍에서 약간의 작업이지만 작동합니다.
그런 것
template<typename SomeType>
shared_ptr(SomeType *p)
{
this->destroyer = destroyer_function<SomeType>(p);
...
}
참고 URL : https://stackoverflow.com/questions/3899790/shared-ptr-magic
'developer tip' 카테고리의 다른 글
PHP 배열 키에 허용되는 문자? (0) | 2020.10.08 |
---|---|
스위치 케이스 순서가 속도에 영향을 줍니까? (0) | 2020.10.08 |
System.Web.Helpers, System.Web.WebPages 및 System.Web.Razor는 어디에서 찾을 수 있습니까? (0) | 2020.10.08 |
Ruby에서 문자열을 분할하고 첫 번째 항목을 제외한 모든 항목을 가져 오는 방법은 무엇입니까? (0) | 2020.10.07 |
Java Byte [] 배열을 비교하는 방법은 무엇입니까? (0) | 2020.10.07 |