2010-12-13 2 views
0

소멸자를 호출하는 세 가지 접근법에 중대한/심각한 차이가 있는지 궁금합니다. 다음 코드를 고려하십시오. main()에 언급 된 두 가지 사례도 고려하십시오. 사례 1의 경우 2, 또는 둘 : 당신이 대답중인 경우에 관한 회신파괴자 접근법 호출하기

class Sample 
{ 
public: 
    ~Sample() 
    { 
     cout << "destructor called" << endl; 
    } 
    void destroyApproach1() { this->~Sample(); } 
    void destroyApproach2() { delete this; } 
}; 

void destroyApproach3(Sample *_this) 
{ 
    delete _this; 
} 

void TestUsingNew() 
{ 
    Sample *pSample[] = { new Sample(), new Sample(),new Sample()}; 
    pSample[0]->destroyApproach1(); 
    pSample[1]->destroyApproach2(); 
    destroyApproach3(pSample[2]); 
} 
void TestUsingPlacementNew() 
{ 
    void *buf1 = std::malloc(sizeof(Sample)); 
    void *buf2 = std::malloc(sizeof(Sample)); 
    void *buf3 = std::malloc(sizeof(Sample)); 
    Sample *pSample[3] = { new (buf1) Sample(), new (buf2) Sample(), new (buf3) Sample()}; 
    pSample[0]->destroyApproach1(); 
    pSample[1]->destroyApproach2(); 
    destroyApproach3(pSample[2]); 
} 
int main() 
{ 
    //Case 1 : when using new 
    TestUsingNew(); 

    //Case 2 : when using placement new 
    TestUsingPlacementNew(); 
    return 0; 
} 

하는 것은 특정하십시오!


또한,이 방법으로 TestUsingPlacementNew()을 작성하려고했지만, 그것은 런타임 예외 (++ 2008 MSVC)을 던지고. 왜 그런지 모르겠다 :

void TestUsingPlacementNew() 
{ 
    const int size = sizeof(Sample); 
    char *buffer = (char*)std::malloc(size * 3); 
    Sample *pSample[] = { new (buffer) Sample(), new (&buffer[size]) Sample(),new (&buffer[2*size]) Sample()}; 
    pSample[0]->destroyApproach1(); 
    pSample[1]->destroyApproach2(); 
    destroyApproach3(pSample[2]); 
} 

아마도 메모리 패딩 및/또는 정렬이 그 이유 일 수 있을까요?


관련 주제 : Destructor not called after destroying object placement-new'ed

답변

5

예, 이러한 접근 방법 사이에 큰 차이가있다 :

  • destroyApproach1에서, 당신은 단지 개체의 소멸자를 호출; 실제로 점유 한 메모리를 해제하지 마십시오.

  • destroyApproach2에서

    destroyApproach3 당신이 개체 의 소멸자와 전화 당신이합니다 (delete 식을 사용하여) 객체가 점유하는 메모리를 해제. 첫 번째 TestUsingPlacementNew 테스트에서는 개체가 차지하는 메모리가 new이 아닌 malloc을 호출하여 처음 할당되었으므로이 두 가지 모두 잘못되었습니다. 당신이 배열의 인덱스 1에있는 객체를 delete을 시도하기 때문에

마지막 시험에서 런타임 오류가 발생합니다; 그 요소에 대한 포인터는 처음에 new에 대한 호출에서 가져 오지 않았습니다. 첫 번째 예제에서는 "작동합니다"("작동"은 실제로 "동작이 정의되지는 않지만 올바르게 작동하는 것처럼 보입니다"라는 의미입니다)

+0

게재 위치를 새로 사용할 때 두 번째 단락이 두 번째 경우입니까? – Nawaz

+0

@Nawaz : 답변을 시도한 부분을 나타내는 답변을 업데이트했습니다. –

+0

업데이트 해 주셔서 감사합니다. :-) – Nawaz

1

delete this은 올바른 방법이 아닙니다. 현대적인 코드 소멸자를 호출하면 소멸자를 호출 할 필요가 없습니다 일반적으로 :. 마법은 그들이 적절한 시간에 호출되는 것입니다 : 모든 경우에

struct A { 
    ~A() { std::cout << "running destructor\n"; } 
}; 

int main() 
{ 
    A a; 
    return 0; 
} 

deletenew에 의해 할당 해제 메모리입니다 new :

에 의해 객체가 할당되지 않은 경우 delete this이 문제를 일으킬 것입니다.
struct B { 
    ~B() { delete this } 
}; 

int main() 
{ 
    B b; 
    return 0; 
} 

실제 운영 체제가있는 거의 모든 플랫폼에서 프로그램을 중단합니다 (기술적으로 정의되지 않은 동작이며 표준 호환 프로그램 자체가 손상되어 계속 실행될 수 있으므로 "거의 모든 것", keep 귀하의 플랫폼이 귀하의 손가락을 넘어서서 손상된 메모리 관리 데이터 구조 및 유효하지 않은 스택과 함께 혼란에 빠지게 할 수 있습니다.배치 new


은 크게 포인터가 특정 주소에 할당해야합니다 하드웨어 장치 드라이버 나 다른 장소를 의미한다. In general you won't want to destroy objects allocated with placement new. 당신은 단순히 직접 소멸자를 호출 할 경우 :

My_object* o = new(0xffff) My_object(); 
o->~My_object(); 

그러나이, 기억, 비얀 스트로브 스트 룹은 소멸자의 "명시 적 호출이 ... 피해야 말했다 가능한 때때로, 그들은 필수적이다 .... 초보자는 명시 적으로 소멸자를 호출하기 전에 세 번 생각해야하며 이렇게하기 전에 경험이 많은 동료에게 물어보십시오. "(The C++ Programming Language, 10.4.11).

관련 문제