2011-09-16 2 views
0

벡터에 대한 포인터가 추가되어 내 프로그램이 실패합니다. 많은 읽기와 삭제 후에 나는 처음에는 괜찮 았지만() 삽입을 사용하여 집합으로 공유 포인터를 추가했지만 지금은 실패합니다. 나는 시도했다 two solutions; 둘 다 일하지 않았다. 하나는 실패했고 다른 하나는 공유 된 종류가 컴파일되지 않았습니다.공유 포인터와의 거래는 무엇입니까?

조금 더 읽기 나는 두 개의 다른 공유 포인터로 뭔가를 가리 키지 말고 그 사본을 작성해야한다고 설명하는이 forum이 나왔습니다. 그렇다면 공유 포인터의 큰 차이점은 무엇입니까?

답변

3

모든 것이 소유권입니다. 엔티티 (함수 또는 객체)는 해당 엔티티의 작업 인 경우 포인터를 "소유"한다고 말하여 포인터가 삭제되었음을 보증합니다. new을 사용할 때마다 누군가 어딘가에이 반환 된 포인터의 소유권을 가져야합니다. 그렇지 않은 경우 메모리 누수가 발생합니다.

모든 종류의 스마트 포인터의 목적은 어떤 형태의 소유권을 모델링하는 것입니다. 스마트 포인터의 소멸자는 포인터의 삭제를 트리거 할 수 있습니다.

std::auto_ptr (복사하지 않는 한) 단일 소유권을 모델로합니다. 즉, auto_ptr 인스턴스가있는 모든 엔티티는 해당 포인터의 파기를 발생시키는 엔티티입니다. 해커 덕분에 auto_ptr을 복사하면 실제로 복사 된 개체의 소유권이 복사 할 개체로 이전됩니다 (참고 : 절대로이 작업을 수행하지 마십시오).

그래서, 당신이있는 경우이 :

std::auto_ptr<int> p1 = new int(4); 

이 파괴 될 보장 (너무 오래 잡고 실체가 제대로 정리 될 때). p1이 스택에서 떨어지면 포인터가 삭제됩니다. p1이 클래스의 구성원이면 해당 클래스 인스턴스가 삭제되면 포인터가 삭제됩니다. 포인터의 유효 기간이 유효합니다. Boost에는 실제로 이라는 복사 할 수없는 동일한 기능이 있습니다.

모든 종류의 스마트 포인터를 사용할 때 준수해야하는 몇 가지 규칙이 있습니다. 이것이 가장 중요합니다.

규칙 # 1 :. 당신이 알몸 포인터에서 스마트 포인터의 인스턴스를 생성하는 경우, 당신은 지금 이니 객체가 현재이 포인터의 소유권이 없다 ", IS 무슨 말을 당신 소유권을주고, 스마트 포인터. " 그것이 알몸 포인터에서 스마트 포인터 개체를 구성한다는 의미입니다.

이 코드는 규칙 # 1의 위반 :

std::auto_ptr<int> p1 = new int(4); 
std::auto_ptr<int> p2 = p1.get(); 

auto_ptr::get() 기능은 포인터를 반환, 그래서 이것은 법적 C++ 코드 (이 컴파일)입니다. 그러나 p1p2은 모두 포인터를 소유하고 있다고 생각합니다. auto_ptr 모델은 단일 - 소유권 만 허용되지 않으므로 허용되지 않습니다. p2이 파괴되면 포인터가 삭제됩니다. 그런 다음 p1이 파괴되면 같은 포인터를 삭제하려고 시도합니다.

이제 우리는 규칙 # 1에 대해 매우 분명합니다. shared_ptr을 보겠습니다. 이 스마트 포인터 모델 공유 소유권. 여러 엔터티가 동시에 포인터의 소유권을 주장 할 수 있습니다. 포인터는 모두이 끝나면 삭제됩니다. 따라서 3 개의 개체에 모두 동일한 개체에 shared_ptr이 포함되어있는 경우 해당 개체는 shared_ptr이 포함 된 세 개의 개체가 모두 삭제 될 때까지 삭제되지 않습니다.

shared_ptr은 스마트 포인터라는 것을 이해하는 것이 중요합니다. 그러므로, 그것은 규칙 # 1의 적용을 받는다.

그건 의미가 없을 수도 있습니다. 결국 공유 소유권을 허용해야합니다. 이것이 허용 가능하다는 것을 의미합니다, 맞죠?

shared_ptr<int> p1 = new int(4); 
shared_ptr<int> p2 = p1.get(); 

아니요. 이것은 여전히 ​​잘못된 것입니다. auto_ptrshared_ptr 사이의 차이점은 shared_ptr이 할 수 있다는 것입니다 :

shared_ptr<int> p1 = new int(4); 
shared_ptr<int> p2 = p1; 

p1에서 p2의 사본 건설 있다고. 알몸 포인터에서 shared_ptr을 생성하고 이미 존재하는 shared_ptr에서 하나를 만드는 것의 근본적인 차이가 있습니다. 후자는 실제로 둘 사이의 소유권을 공유합니다. 전자는 단지 나쁜 일을 일으킬 것입니다.

따라서 알몸 포인터가 있고 shared_ptr에 넣은 경우 해당 포인터 에 대해서만 한 번만 수행 할 수 있습니다. 소유권을 공유하려는 경우 소유권을 복사해야합니다.

하나의 세미 백도어가 있습니다 : enable_shared_from_this. 이 유형에서 클래스를 파생 한 경우 클래스에는 클래스의 멤버 함수가 소유권을 이전하는 데 사용할 수있는 shared_from_this 개인 멤버가 있습니다.따라서 :

struct Type : public enable_shared_from_this 
{ 
    DoSomething() 
    { 
    shared_ptr<Type> p2 = shared_from_this(); 
    FunctionThatTakesOwnership(p2); 
    } 
}; 

shared_ptr<Type> p1 = new Type; 
p1->DoSomething(); 

이외의 경우 명시 적으로 개체를 복사하여 소유권을 이전해야합니다.

+0

감사합니다. 훌륭한 답변입니다. 나는 아직도 하나의 질문을 가지고있다. stl 컨테이너가 (insert, push_back 등 ...) 복사 생성자로 계산을 추가합니까? (어느 쪽이 맞습니까? – Yotam

+0

@ Yotam : 예, 매개 변수를 복사합니다. 'shared_ptr'의 컨테이너를 가지는 것이 안전합니다. –

2

shared_ptr은 shared_ptr이 가리키는 개체가 다른 위치에서 참조되는 경우 이름 상태로 사용해야합니다.

예를 들어, - 클래스 A1과 A2는 동일한 유형의 객체 S를 사용해야합니다. 그래서 둘 다 S에 대한 포인터를 보유해야합니다. 그러나 누가 그것을 소유해야합니다 (누가 그것을 삭제해야하는지). A1을 가정 해 봅시다. 그래서, 소멸자의 A1은 S를 지울 것입니다.하지만 A2가 A2보다 먼저 파괴되면 A (삭제 된 객체에 대한 포인터)가 S에 매달리게됩니다. S (S *)에 대한 원시 포인터 대신 shared_ptr을 사용하면이 문제가 해결됩니다.

+0

내가 생각한 것이지만 왜 그것을 사용하기 전에 공간을 할당해야합니까 (다른 곳으로 가리킬 수 있습니까?). 포인터를 취할 생성자가없는 이유는 무엇입니까? 즉, 이미 존재하고 뾰족한 객체에 대한 포인터를 추가 할 때마다 어떻게 새로운 객체를 생성하지 않도록 할 수 있습니까? – Yotam

0

공유 포인터 은 가리킨 개체의 소유권을 가져옵니다.

이 의미 론적 의미는 shared_ptr이 복사 될 때 각자가 차례로 소유권에 대한 공유 된 지식을 처리한다는 점입니다. 마지막 사본이 파괴되면 객체를 파괴합니다. 이렇게하면 적절한 시간에 delete에 대한 호출을 수동으로 관리하지 않아도되고 (잘하면) 메모리 누수가 적어집니다.

이 작업을 수행하려면 정상적인 스타일은 new 힙 오브젝트를 shared_ptr에 작성한 후이를 생 포인터로 직접 작업하지 않는 것이 좋습니다.

STL 세트 내에서 shared_ptr을 올바르게 사용하고 있습니다. 이것은 세트가 파기되었을 때에 오브젝트가 정리되도록 (듯이)하는 올바른 방법입니다.

관련 문제