shared_ptr 및 weak_ptr 차이점
Scott Meyers "Effective C ++"책을 읽고 있습니다. 내장 포인터 가 tr1::shared_ptr
있고 tr1::weak_ptr
그처럼 작동한다고 언급 되었지만 tr1::shared_ptrs
, 객체를 가리키는 지점 수를 추적 합니다.
이를 참조 계수라고합니다. 이것은 비 tr1::shared_ptrs
주기적 데이터 구조에서 리소스 누출을 방지하는 데 효과적이지만, 둘 이상의 객체 에주기가 형성되는 것과 같은 포함 된 경우주기에 대한 모든 외부 포인터가 파괴 된 경우에도주기가 서로의 참조 카운트를 0 이상으로 유지할 수 있습니다.
그것이 tr1::weak_ptrs
들어오는 곳 입니다.
내 질문은 순환 데이터 구조가 참조 횟수를 0 이상으로 만드는 방법입니다. 예제 C ++ 프로그램을 요청합니다. 문제는 어떻게 해결 weak_ptrs
됩니까? (다시 예를 들어주세요).
A shared_ptr
는 원시 포인터 주위에 참조 계수 메커니즘을 감 쌉니다. 따라서 shared_ptr
참조 횟수 의 각 인스턴스에 대해 1 씩 증가합니다. 두 share_ptr
개체가 서로를 참조하면 참조 횟수가 0이되지 않으므로 삭제되지 않습니다.
weak_ptr
를 가리 shared_ptr
키지 만 참조 횟수를 늘리지는 않습니다. 즉, 참조가 있더라도 하위 개체를 삭제할 수 있습니다 weak_ptr
.
이것이 작동하는 방식 은 기본 객체를 사용하고 싶을 때마다 for weak_ptr
를 만드는 데 사용할 수 있다는 것 shared_ptr
입니다. 그러나 객체가 이미 삭제 된 경우 a의 빈 인스턴스 shared_ptr
가 반환됩니다. 기본 개체에 대한 참조 횟수가 참조로 증가하지 않기 때문에 weak_ptr
순환 참조로 인해 기본 개체가 삭제되지 않습니다.
"제 질문, 순환 데이터 구조가 어떻게 참조 카운트를 0 이상으로 만드는지, 친절하게 C ++ 프로그램에서 예제와 함께 보여달라고 요청하십시오. 어떻게 문제가 weak_ptrs
다시 예제를 통해 해결되는지 확인하십시오."
이 문제는 다음과 같은 C ++ 코드에서 발생합니다 (개념 상).
class A { shared_ptr<B> b; ... };
class B { shared_ptr<A> a; ... };
shared_ptr<A> x(new A); // +1
x->b = new B; // +1
x->b->a = x; // +1
// Ref count of 'x' is 2.
// Ref count of 'x->b' is 1.
// When 'x' leaves the scope, there will be a memory leak:
// 2 is decremented to 1, and so both ref counts will be 1.
// (Memory is deallocated only when ref count drops to 0)
질문의 두 번째 부분에 답하기 위해 : 참조 계산이주기를 처리하는 것은 수학적으로 불가능합니다. 따라서 a weak_ptr
(기본적으로의 제거 된 버전 shared_ptr
) 는 사이클 문제를 해결하는 데 사용할 수 없습니다 . 프로그래머가 사이클 문제를 해결하고 있습니다.
이를 해결하기 위해 프로그래머 는 객체 간의 소유권 관계를 알고 있어야 하거나 그러한 소유권이 자연적으로 존재하지 않는 경우 소유권 관계를 만들어야합니다.
위의 C ++ 코드는 A가 B를 소유하도록 변경할 수 있습니다.
class A { shared_ptr<B> b; ... };
class B { weak_ptr<A> a; ... };
shared_ptr<A> x(new A); // +1
x->b = new B; // +1
x->b->a = x; // No +1 here
// Ref count of 'x' is 1.
// Ref count of 'x->b' is 1.
// When 'x' leaves the scope, its ref count will drop to 0.
// While destroying it, ref count of 'x->b' will drop to 0.
// So both A and B will be deallocated.
중요한 질문은 다음과 같습니다. weak_ptr
프로그래머가 소유권 관계를 말할 수없고 권한 부족 또는 정보 부족으로 인해 정적 소유권을 설정할 수없는 경우 사용할 수 있습니까?
대답은 다음과 같습니다. 객체 간의 소유권이 명확하지 weak_ptr
않으면 도움이 될 수 없습니다 . 사이클이 있다면 프로그래머는 그것을 찾아 깨뜨려야합니다. 대체 방법은 전체 가비지 수집 (예 : Java, C #, Go, Haskell)이있는 프로그래밍 언어를 사용하거나 C / C ++에서 작동하는 보수적 (= 불완전한) 가비지 수집기를 사용하는 것입니다 (예 : Boehm GC). .
미래의 독자를 위해.
Atom이 제공하는 설명이 훌륭하다는 것을 지적하고 싶습니다. 여기에 작업 코드가 있습니다.
#include <memory> // and others
using namespace std;
class B; // forward declaration
// for clarity, add explicit destructor to see that they are not called
class A { public: shared_ptr<B> b; ~A() {cout << "~A()" << endl; } };
class B { public: shared_ptr<A> a; ~B() {cout << "~B()" << endl; } };
shared_ptr<A> x(new A); //x->b share_ptr is default initialized
x->b = make_shared<B>(); // you can't do "= new B" on shared_ptr
x->b->a = x;
cout << x.use_count() << endl;
Weak pointers just "observe" the managed object; they don't "keep it alive" or affect its lifetime. Unlike shared_ptr
, when the last weak_ptr
goes out of scope or disappears, the pointed-to object can still exist because the weak_ptr
does not affect the lifetime of the object - it has no ownership rights. The weak_ptr
can be used to determine whether the object exists, and to provide a shared_ptr
that can be used to refer to it.
The definition of weak_ptr
is designed to make it relatively foolproof, so as a result there is very little you can do directly with a weak_ptr
. For example, you can't dereference it; neither operator*
nor operator->
is defined for a weak_ptr
. You can't access the pointer to the object with it - there is no get()
function. There is a comparison function defined so that you can store weak_ptrs
in an ordered container, but that's all.
All the above answer are WRONG. weak_ptr
is NOT used to break cyclic references, they have another purpose.
Basically, if all shared_ptr(s)
were created by make_shared()
or allocate_shared()
calls, you will NEVER need weak_ptr
if you have no resource other than memory to manage. These functions create the shared_ptr
reference counter object with the object itself, and the memory will be freed at the same time.
The only difference between weak_ptr
and shared_ptr
is that the weak_ptr
allows the reference counter object to be kept after the actual object was freed. As a result, if you keep a lot of shared_ptr
in a std::set
the actual objects will occupy a lot of memory if they are big enough. This problem can be solved by using weak_ptr
instead. In this case, you have to ensure the weak_ptr
stored in the container is not expired before using it.
참고URL : https://stackoverflow.com/questions/4984381/shared-ptr-and-weak-ptr-differences
'Nice programing' 카테고리의 다른 글
TypeScript의 EventTarget 유형에 'value'속성이 없습니다. (0) | 2020.11.03 |
---|---|
Eclipse 문제보기가 더 이상 오류를 표시하지 않음 (0) | 2020.11.03 |
Mongo에서 .find ()를 수행 할 때 .findOne ()을 수행하는 것과 동일한 결과를 표시하려면 어떻게해야합니까? (0) | 2020.11.03 |
창을 닫을 때 JavaFX 응용 프로그램을 닫는 방법은 무엇입니까? (0) | 2020.11.03 |
SQL Server에서 테이블 및 인덱스 저장소 크기 가져 오기 (0) | 2020.11.03 |