2013-08-04 3 views
1

나는 shared_ptr 및 weak_ptr에 대해 학습하기 시작했습니다. 이론 상으로는 모든 것이 단순 해 보입니다. 하지만 테스트를 시작했을 때, 음 ...이 간단한 프로그램이 있습니다.shared_ptr.reset() 삭제하지 않음

#include <iostream> 
#include <memory> 
using namespace std; 

class Second 
{ 
public: 
    Second() 
    { 
     cout << "Second created" << endl; 
    } 
    ~Second() 
    { 
     cout << "Second deleted" << endl; 
    } 
}; 

class Main 
{ 
public: 
    shared_ptr<Second> second; 
    Main() 
    { 
     cout << "Main created" << endl; 
     second = make_shared<Second>(*(new Second())); 
    } 
    ~Main() 
    { 
     second.reset(); 
     cout << "Main deleted" << endl; 
    } 
}; 

void fun() 
{ 
    shared_ptr<Main> main = make_shared<Main>(*(new Main())); 
} 

int main() 
{ 
    cout << "Program started" << endl; 
    fun(); 

    cout << "Program ended" << endl; 
    return 0; 
} 

문제는 두 번째가 삭제되지 않는다는 것입니다. 세드릭

Program started 
Main created 
Second created 
Main deleted 
Program ended 

: 여기 내 출력은? 나는 shared_ptr과 그 마지막 shared_ptr을 리셋하면 객체가 자동으로 삭제된다는 것을 알았다.

+1

이게 뭐야 :'make_shared (* (새 초)));'? 힙에 객체를 만든 다음 다른 객체에 복사합니다. 원본은 결코 삭제되지 않습니다! 'make_shared ();' –

+0

@ DeX3r'make_shared'의 매개 변수를 사용하여 생성자가 매개 변수를 필요로하는 클래스를 초기화해야합니다. – quamrana

답변

8

공유 포인터를 잘못 초기화하고 있습니다. make_shared을 사용할 때 new을 전혀 사용할 필요가 없습니다. make_shared에 전달하는 매개 변수는 만들고있는 클래스의 생성자로 전달됩니다. 다음과 같아야 코드에 따라서

, 당신의 make_shared 전화 :

shared_ptr<Main> main = make_shared<Main>(); 

하고 대신

shared_ptr<Second> main = make_shared<Second>(); 

, 당신은 새로운 사용하여 각 클래스 (버전을 유출 한 일 명시 적으로 삭제하지 않음) 누수 된 값을 두 번째 버전으로 복사합니다. 내가 말했듯이 상황이 매우 복잡하다,

Second *p = new Second; 
shared_ptr<Second> ss = make_shared<Second>(*p); // Calls the Second class copy constructor 
// p is never deleted, so it is leaked. 
+0

그래서'make_shared '가 만든'Second' 인스턴스의 파괴를 결코 볼 수 없습니까? – quamrana

+1

필자는 더 이상 아시아 프로그래머를 믿지 않았다 : P http://www.youtube.com/watch?feature=player_detailpage&v=V3aLw_9lBDc&t=290 –

+1

@quamrana : 당신이'Main'의 복사 생성자를 오버라이드하지 않았으므로' 두 번째 '가 복사됩니다.따라서'Main'을 유출 할 때'shared_ptr '도 누설됩니다.이 참조가 사라질 때까지 그리고 의도적으로'delete'가 발생하지 않습니다 ... –

2

, 그래서 스키마가 필요합니다 여러 줄로 표현을 분할함으로써, 우리는보다 쉽게 ​​잘못 한 일을 볼 수 있습니다.

class Main { 
public: 
    shared_ptr<Second> second; 
    Main() 
    { 
     cout << "Main created" << endl; 
     second = make_shared<Second>(*(new Second())); 
    } 
    ~Main() 
    { 
     second.reset(); 
     cout << "Main deleted" << endl; 
    } 
}; 

void fun() 
{ 
    shared_ptr<Main> main = make_shared<Main>(*(new Main())); 
} 

오른쪽 main의 생성 후, 우리는이 : main.second이 너무 <anon>.second에서 복사

<anon: Second> (leaked) 

<anon: Main> (leaked) 
      \ 
      |---> <Main.second: Second> 
      /
<main: Main> 

하는 것으로, 사람들은 Second의 동일한 인스턴스에 둘 점 shared_ptr<Second>이기 때문에.

<anon: Second> (leaked) 

<anon: Main> (leaked) ---> <Main.second: Second> (indirectly leaked) 

second.reset() 것을 반드시 지적이-하는 객체를 파괴하지 않습니다

그런 다음, main 다이, 우리는 남아 있습니다. 단순히 shared_ptr의 로컬 인스턴스를 재설정합니다. 이 개체를 가리키는 마지막 인스턴스 인 경우 개체가 삭제되지만 그렇지 않은 경우는 없습니다.

+0

그리고 "second.reset();"도 필요하지 않습니다. 주 소멸자, 맞죠? 나는 그것 없이는 작동하지만 그것은 맞습니까? –

+0

@ DeX3r : correct. –

관련 문제