class A {};
void f(A* a) {
shared_ptr<A> c(a);
}
int main() {
auto a = make_shared<A>();
auto b = a.get();
f(b);
return 0;
}
. f(b)
에 전화하면 같은 데이터를 소유하고 있다고 생각하는 관련없는 두 번째 공유 포인터가 생성됩니다. 함수 호출 f()
이 끝나면 로컬 공유 ptr 변수가 삭제됩니다. 이는 참조 카운트가 0인지 여부를 확인하므로 객체를 삭제합니다. 그런 다음 주 함수가 끝나면 로컬 변수 a
에 대한 소멸자가 실행되고 참조 횟수가 0 (다시 계산 됨)인지 확인하여 동일한 데이터를 두 번 삭제하려고합니다. 이 이중 삭제는 충돌을 일으키는 원인입니다.
두 가지 해결책이 있습니다. 가장 쉬운 방법은 원시 포인터를 처리하지 않고 을 f()
에 직접 전달하는 것입니다. 그러면 참조 계산이 올바르게 작동하고 데이터가 한 번만 파괴됩니다.
또 다른 방법은 A
클래스를 std::enable_shared_from_this
으로 공개적으로 상속받는 것입니다. 즉
class A : public std::enable_shared_from_this<A> {};
void f(A* a) {
shared_ptr<A> c = a->shared_from_this();
}
당신은 약 enable_shared_from_this
here를 읽을 수 있습니다 그럼 당신은, 원시 포인터에서 (올바른 참조 카운팅) 공유 포인터를 "복구"로 shared_from_this()
방법을 사용할 수 있습니다.
올리버가 맞습니다. 이러지 마! 'std :: shared_ptr'는 동일한 shared_ptr이 서로를 인식하고있는 한 동일한 sharling을 허용합니다. 원시 포인터를 꺼내고 다른 shared_ptr에 소유권을 부여하자마자 각각의 소유주가 독점권을 가지고 있다는 것을 알고있는 독립 소유자가 있습니다 (또는 shared_ptr의 경우 공유 된 연합 소유권이며 두 개의 분리 된 소유자가 있습니다). "연합"). – Eljay