2012-02-14 2 views
5

Alexandrescu와 wikipipidia 읽기 pointee와 참조 카운터가 힙에 저장되어있는 것을 볼 수 있습니다. 그렇다면 카운터가 힙에 할당되어야하므로 참조 계산이 비효율적이라는 언급이 있습니까? 스택에 저장되지 않는 이유는 무엇입니까?왜 C++ 스마트 포인터 구현은 pointee와 함께 힙에 참조 카운터를 유지합니까?

+0

설명하는 내용의 예를 보여줄 수 있습니까? –

+0

다른 방법은 무엇입니까? –

+0

"참조 카운터"와 "힙"은 단순한 구현 세부 사항입니다.실제 쇠고기는 공유 소유권 의미론이 동적 할당으로 만 구현 될 수 있다는 것입니다. –

답변

9

스마트 포인터의 현재 인스턴스가 범위를 벗어나 자마자 잃게 될 것이기 때문입니다.

스마트 포인터는 동적으로 할당 된 자동 저장 개체를 시뮬레이트하는 데 사용됩니다. 스마트 포인터 자체는 자동으로 관리됩니다. 따라서 하나가 파괴되면 자동 저장 장치에 저장되는 모든 것도 파괴됩니다. 그러나 참조 카운터를 잃고 싶지는 않습니다. 따라서 동적 저장소에 저장합니다.

3

개체의 복사본이 refcount 복사본을 생성하여 목적을 달성하지 못하기 때문에 스택에 저장할 수 없습니다. 다른 사람들이 지적했듯이

1

, 스택 개체가 현재 스택 프레임 오래 살 수 있기 때문에 참조 카운트를 유지하기 위해 적절한 장소가 아니다 (참조 횟수가 사라질 것이다 경우를!)

그것은 가치 참조 횟수를 힙에 넣는 것과 관련된 비효율의 일부는 객체 자체와 함께 "함께"저장함으로써 극복 될 수 있음을 지적했습니다. 부스트는 boost::make_shared (shared_ptr의 경우) 또는 boost::intrusive_ptr을 사용하여 수행 할 수 있습니다.

1

다른 용도로 설계된 스마트 포인터에는 여러 가지 유형이 있습니다. 얘기하고있는 포인터는 공유 스마트 포인터 (std::shared_ptr)이며 여러 위치에서 개체 소유권을 공유하는 데 도움이됩니다. shared_ptr의 모든 사본은 첫 번째 사본이 종료 된 후에도 shared_ptr의 모든 사본에서 사용 가능해야하므로 동일한 카운터 변수를 힙에 두어 증가 및 감소시킵니다.

따라서 shared_ptr은 개체와 카운터에 두 개의 포인터를 내부적으로 유지합니다. 의사 코드 : 그런데

class SharedPointer<T> { 
public: 
// ... 
private: 
    T* obj; 
    int* counter; 
} 

, 당신은 std::make_shared으로 객체를 생성 할 때, 구현이 카운터와 객체 모두를 유지하기에 충분한 메모리를 할당 한 다음이 나란히 구성하여 할당을 최적화 할 수 있습니다.

이 트릭은 극단적으로 우리에게 간섭을 일으키는 참조 카운팅 패턴을 제공합니다. 개체는 내부적으로 카운터를 보유하고 있으며이를 증가 및 감소시키는 AddRefRelease 함수를 제공합니다. 간섭 스마트 포인터을 사용할 수 있습니다. boost::intrusive_ptr,이 기계를 사용하므로 다른 별도의 카운터를 할당 할 필요가 없습니다. 이것은 할당 측면에서 더 빠르지 만 카운터를 제어 된 클래스 정의에 삽입해야합니다. std::unique_ptr 또는 boost::scoped_ptr : 당신이 스마트 포인터을 범위 사용할 수 있습니다 당신이 공유 객체의 소유권을 필요로하고 단지 그것을 평생의 통제 할 필요가 없습니다 또한

은 (함수가 리턴 할 때 너무 즉 파괴됩니다). unique_ptr의 복사본이 하나뿐이므로 카운터가 모두 필요하지 않습니다.