Alexandrescu와 wikipipidia 읽기 pointee와 참조 카운터가 힙에 저장되어있는 것을 볼 수 있습니다. 그렇다면 카운터가 힙에 할당되어야하므로 참조 계산이 비효율적이라는 언급이 있습니까? 스택에 저장되지 않는 이유는 무엇입니까?왜 C++ 스마트 포인터 구현은 pointee와 함께 힙에 참조 카운터를 유지합니까?
답변
스마트 포인터의 현재 인스턴스가 범위를 벗어나 자마자 잃게 될 것이기 때문입니다.
스마트 포인터는 동적으로 할당 된 자동 저장 개체를 시뮬레이트하는 데 사용됩니다. 스마트 포인터 자체는 자동으로 관리됩니다. 따라서 하나가 파괴되면 자동 저장 장치에 저장되는 모든 것도 파괴됩니다. 그러나 참조 카운터를 잃고 싶지는 않습니다. 따라서 동적 저장소에 저장합니다.
개체의 복사본이 refcount 복사본을 생성하여 목적을 달성하지 못하기 때문에 스택에 저장할 수 없습니다. 다른 사람들이 지적했듯이
는, 스택 개체가 현재 스택 프레임 오래 살 수 있기 때문에 참조 카운트를 유지하기 위해 적절한 장소가 아니다 (참조 횟수가 사라질 것이다 경우를!)
그것은 가치 참조 횟수를 힙에 넣는 것과 관련된 비효율의 일부는 객체 자체와 함께 "함께"저장함으로써 극복 될 수 있음을 지적했습니다. 부스트는 boost::make_shared (shared_ptr의 경우) 또는 boost::intrusive_ptr을 사용하여 수행 할 수 있습니다.
다른 용도로 설계된 스마트 포인터에는 여러 가지 유형이 있습니다. 얘기하고있는 포인터는 공유 스마트 포인터 (std::shared_ptr
)이며 여러 위치에서 개체 소유권을 공유하는 데 도움이됩니다. shared_ptr
의 모든 사본은 첫 번째 사본이 종료 된 후에도 shared_ptr
의 모든 사본에서 사용 가능해야하므로 동일한 카운터 변수를 힙에 두어 증가 및 감소시킵니다.
따라서 shared_ptr
은 개체와 카운터에 두 개의 포인터를 내부적으로 유지합니다. 의사 코드 : 그런데
class SharedPointer<T> {
public:
// ...
private:
T* obj;
int* counter;
}
, 당신은 std::make_shared
으로 객체를 생성 할 때, 구현이 카운터와 객체 모두를 유지하기에 충분한 메모리를 할당 한 다음이 나란히 구성하여 할당을 최적화 할 수 있습니다.
이 트릭은 극단적으로 우리에게 간섭을 일으키는 참조 카운팅 패턴을 제공합니다. 개체는 내부적으로 카운터를 보유하고 있으며이를 증가 및 감소시키는 AddRef
및 Release
함수를 제공합니다. 간섭 스마트 포인터을 사용할 수 있습니다. boost::intrusive_ptr
,이 기계를 사용하므로 다른 별도의 카운터를 할당 할 필요가 없습니다. 이것은 할당 측면에서 더 빠르지 만 카운터를 제어 된 클래스 정의에 삽입해야합니다. std::unique_ptr
또는 boost::scoped_ptr
: 당신이 스마트 포인터을 범위 사용할 수 있습니다 당신이 공유 객체의 소유권을 필요로하고 단지 그것을 평생의 통제 할 필요가 없습니다 또한
은 (함수가 리턴 할 때 너무 즉 파괴됩니다). unique_ptr
의 복사본이 하나뿐이므로 카운터가 모두 필요하지 않습니다.
설명하는 내용의 예를 보여줄 수 있습니까? –
다른 방법은 무엇입니까? –
"참조 카운터"와 "힙"은 단순한 구현 세부 사항입니다.실제 쇠고기는 공유 소유권 의미론이 동적 할당으로 만 구현 될 수 있다는 것입니다. –