2013-09-25 7 views
2

new Time(1,0,0)으로 SmartPtr 클래스를 초기화합니다.`new '로 만든 임시 객체에서'delete '가 호출되는시기는 언제입니까?

//main.cpp 
    int main() 
{ 
    SmartPtr pTime0(new Time(0,0,1)); 
} 

여기 new Time(1,0,0)에서 삭제를 부르고 있습니다. 모든 것이 잘 작동하며, 프로그램은이를 준수하고 실행됩니다. 하지만 혼란 스럽네요 - 어디서해야합니까 /하지 말아야합니까? delete Time(1,0,0)?

여기서 임시 개체 생성 및 삭제의 개념을 이해하지 못합니다. 내가 쓸 때마다 new 어딘가에 내가 delete을 써야한다는 것을 안다! 누군가 delete Time(1,0,0)이 어디에서 발생하는지 설명해주세요.

SmartPtr pTime0 (새 시간 (0,0,1)) < - new 여기서 새롭게 할당 된 메모리에 대한 포인터를 반환하고 ctor에서 두 번째로 new 메모리를 할당합니까 ??

//SmartPtr.cpp 

SmartPtr::SmartPtr(Pointee * p):_pointee(new Pointee(*p)) 
{} 

SmartPtr::~SmartPtr() 
{ 
    delete _pointee; 
} 
+0

가 SmartPtr 당신이 디자인 클래스가 따라야한다? 개체 수명을 잘 관리하여 클래스가 삭제할시기를 결정할 수 있습니다. –

+5

SmartPtr의 ctor에있는 힙에 새 Pointee를 만드는 이유가 이해가 안됩니다. 이것은 당신이 원하는 것이 아닙니다. 단순히'_pointee (p)'라고 써야합니다. 즉, 주어진 포인터와 동일한 포인터를 사용하면됩니다. 귀하의 진술은 새로운 Pointee를 할당하고 그것에 제공된 포인터의 내용을 복사합니다. – leemes

+0

'_pointee (p)'하고 싶지 않습니다. p (new Time (0,0,1))이 수업 외 다른 곳에서 만들어지면 어딘가에 삭제 될 수도 있고 ('delete p'), SmartPtr 소멸자는'delete _pointee''(p)', 그래서 런타임 오류가 발생합니다.달성하고자하는 개념은 ctor에 메모리를 할당하고 dtor에서 메모리를 삭제하는 것입니다. – Oleksandra

답변

2

SmartPtr 클래스에 대한 세부 사항을 모르겠습니다. 어떤 경우

,이 같은 생성자가있는 경우 :

SmartPtr::SmartPtr(Pointee * p):_pointee(new Pointee(*p)) 
{} 

을하고이 소멸자입니다 :이 코드를 다음

SmartPtr::~SmartPtr() 
{ 
    delete _pointee; 
} 

:

SmartPtr pTime0(new Time(0,0,1)); 

Time(0,0,1)의 인스턴스가 누출되었습니다.

단계 # 1 :

사실, 당신이 한 번 더 newdelete 이상 (2 new의 1 delete)가 당신은 new Time(0,0,1)를 호출하고 힙에 새로운 개체를 만듭니다.
(new 카운트 == 1)

단계 # 2 : 당신은 전체 복사본 이전에 생성 된 객체와는 힙에 새 복사본을 할당하고를 통해이 복사본을 추적 SmartPtr 생성자,이 포인터를 전달의 _pointee 데이터 회원
(new 카운트 == 2)

단계 # 3 : SmartPtr 소멸자가 실행이, 그것은 delete의 인스턴스가 _pointee 데이터 멤버가 가리키는 있지만 new Time(0,0,1)와 힙에 생성 firts Time(...)를 유출합니다. ;
(delete 카운트 == 1 new 카운트 == 2) 그것에 대해 가능한 수정 될 수

는이 생성자를 가질 :

SmartPtr::SmartPtr(Pointee * p) 
    : _pointee(p) // <--- transfer ownerhsip (no deep copies) ! 
{} 

잠재적 누수를 확인하는 쉬운 방법 이 경우 콘솔 추적 출력을 Time 클래스 생성자와 소멸자에 넣고 소멸자의 추적 출력이 생성자의 추적 출력과 일치하는지 확인하십시오 (예 :

Time::Time(....) 
{ 
    // Do construction work.... 

    std::cout << "Time constructor\n"; 
} 

Time::~Time(....) 
{ 
    // Do destructor work.... 

    std::cout << "Time destructor\n"; 
} 
)

"Time constructor" 문자열의 총 수는 "Time destructor" 개의 문자열 총 수와 일치해야합니다. 수정

+0

//main.cpp SmartPtr ptTime (새 시간 (0,0,1)); 다음을 제공합니다 : 시간 ctor (0,0,1) SmartPtr ctor SmartPtr dtor 시간 dtor (0,0,1). 왜 프로그램이 중단되지 않는가 ?? 메모리 누수가있는 경우 – Oleksandra

+0

로깅의 경우 복사 생성자도 잊지 마세요. – Jarod42

+0

소멸자의 수와 일치해야하는 ctors의 수 (아무리 복사해도 기본값이든간에)? 만약 그렇다면, 실제로 나는 시간 ctor, 시간 복사 ctor, SmartPtr ctor, SmartPtr dtor, 그리고 오직 1 시간 소멸자 !! – Oleksandra

0

new Time(0,0,1)은 힙의 영구 개체에 대한 임시 포인터를 만듭니다. 임시 포인터는 실제로 자동으로 소멸되며 (no-op 임), 오브젝트는 힙에 남아 있지만 참조되지는 않습니다. 누수가 발생했습니다.

누출을 방지하려면 포인터를 어딘가에 저장하고 삭제가 결국 호출되도록하십시오.

1

두 가지 방법 :

방법 A, 호출자가 할당 SmartPtr 소요 소유권 :

SmartPtr::SmartPtr(Pointee * p):_pointee(p) 
{ 
} 

방법 B는 발신자 콘텐츠를 제공하고 SmartPtr는 할당 :

SmartPtr::SmartPtr(Pointee v):_pointee(new Pointee(std::move(v))) 
{ 
} 

그리고 소멸자 동일하게 유지 :

SmartPtr::~SmartPtr() 
{ 
    delete _pointee; 
} 
0

원칙에 따라 애플리케이션을 작성할 수 있습니다.을 입력하지 마십시오.
는 스마트 포인터를 기존과이 결합, 그것은된다 :

#include <memory> // this is where the smart-pointers live 
#include "Time.h" // or whatever header defines your "Time" class 

int main() 
{ 
    // note that make_shared is essentially a forwarding constructor, 
    // give it whatever parameters Time's constructor would take 
    auto p = std::make_shared<Time>(0,0,1); 
    // use p here 
} 

을 그리고 지금까지 아무것도 더 누수가 없을 것입니다.

낮은 수준의 리소스 관리 라이브러리를 작성해야하는 경우를 제외하고는 "예외 없음"이 모든 응용 프로그램 프로그래밍에 적용되어야합니다 ( 제외).

클래스가 리소스 관리를 수행하는 경우 단독 기능이어야합니다.

모든 다른 클래스는 rule of zero