서브 클래스에 대한 포인터에서 기본 클래스 소멸자를 호출하는 포인터에서 삭제합니까?

StackOverflow https://stackoverflow.com/questions/677653

문제

나는있다 class A 필드 중 하나에 힙 메모리 할당을 사용합니다. 클래스 A는 인스턴스화되고 다른 클래스에서 포인터 필드로 저장됩니다 (class B.

클래스 B의 대상을 완료하면 전화 delete, 나는 어느 것이 소멸자라고 부른다고 가정하지만 ... 이것은 클래스 A의 소멸자라고 부릅니까?

편집하다:

답에서 나는 그것을 취한다 (틀린 경우 편집하십시오) :

  1. delete b 호출 b :: ~ b ()의 인스턴스;
  2. 어떤 전화 A::~A();
  3. A::~A ~해야 한다 명시 적으로 delete A 객체의 모든 힙합 구성원 변수;
  4. 마지막으로 클래스 B의 인스턴스가 힙으로 반환됩니다. 새로운 사용되었고, 먼저 힙에 메모리 블록을 할당 한 다음 생성자를 초기화하기 위해 호출했습니다. 이제 모든 파괴자가 호출 된 후 객체가 상주 한 블록을 힙으로 반환합니다.
도움이 되었습니까?

해결책

평생이 끝났을 때 A의 소멸자는 실행됩니다. 메모리가 해제되고 소멸자가 실행되기를 원한다면 힙에 할당 된 경우 삭제해야합니다. 스택에 할당 된 경우 자동으로 발생합니다 (즉, 범위를 벗어날 때; RAII 참조). 클래스의 구성원 인 경우 (포인터가 아니라 정식 구성원), 이는 포함 된 물체가 파괴 될 때 발생합니다.

class A
{
    char *someHeapMemory;
public:
    A() : someHeapMemory(new char[1000]) {}
    ~A() { delete[] someHeapMemory; }
};

class B
{
    A* APtr;
public:
    B() : APtr(new A()) {}
    ~B() { delete APtr; }
};

class C
{
    A Amember;
public:
    C() : Amember() {}
    ~C() {} // A is freed / destructed automatically.
};

int main()
{
    B* BPtr = new B();
    delete BPtr; // Calls ~B() which calls ~A() 
    C *CPtr = new C();
    delete CPtr;
    B b;
    C c;
} // b and c are freed/destructed automatically

위의 예에서는 모든 삭제 및 삭제 []가 필요합니다. 그리고 내가 그것을 사용하지 않은 곳에 삭제가 필요하지 않습니다 (또는 실제로 사용할 수 있음).

auto_ptr, unique_ptr 그리고 shared_ptr 기타 ...이 평생 관리를 훨씬 쉽게 만들 수 있습니다.

class A
{
    shared_array<char> someHeapMemory;
public:
    A() : someHeapMemory(new char[1000]) {}
    ~A() { } // someHeapMemory is delete[]d automatically
};

class B
{
    shared_ptr<A> APtr;
public:
    B() : APtr(new A()) {}
    ~B() {  } // APtr is deleted automatically
};

int main()
{
    shared_ptr<B> BPtr = new B();
} // BPtr is deleted automatically

다른 팁

새로 할당 된 포인터에서 삭제를 호출하면 지적 된 대상의 소멸자가 호출됩니다.

A * p = new A;

delete p;    // A:~A() called for you on obkect pointed to by p

그것은 "deconstructor"가 아닌 "Destructor"입니다.

각 클래스의 파괴자 내부에서는 새로 할당 된 다른 모든 멤버 변수를 삭제해야합니다.

편집 : 명확히하기 위해 :

당신이 가지고 있다고 말하십시오

struct A {}

class B {
    A *a;
public:
    B () : a (new A) {}
    ~B() { delete a; }
};

class C {
    A *a;
public:
    C () : a (new A) {}        
};

int main () {
    delete new B;
    delete new C;
}

B의 인스턴스를 할당 한 다음 삭제하는 것이 깨끗합니다. B가 내부적으로 할당되는 것은 파괴자에서 삭제되기 때문입니다.

그러나 클래스 C의 사례는 메모리가 누출되지 않습니다. 메모리는 릴리스되지 않은 A의 인스턴스를 할당하기 때문에 메모리가 누출됩니다 (이 경우 C에는 소멸자가 없습니다).

일반적인 포인터가있는 경우 (A*) 그러면 소멸자는 호출되지 않습니다 (및 메모리는 A 당신이하지 않는 한 인스턴스가 해제되지 않습니다) delete 명시 적으로 B의 파괴자. 자동 파괴를 원한다면 스마트 포인터를보십시오. auto_ptr.

당신은 B의 소멸자에서 자신을 삭제해야합니다.

class B
{
public:
    B()
    {
       p = new int[1024];  
    }
    virtual ~B()
    {
        cout<<"B destructor"<<endl;
        //p will not be deleted EVER unless you do it manually.
    }
    int *p;
};


class D : public B
{
public:
    virtual ~D()
    {
        cout<<"D destructor"<<endl;
    }
};

할 때 :

B *pD = new D();
delete pD;

기본 클래스에 가상 키워드가있는 경우에만 소멸자가 호출됩니다.

그런 다음 가상 소멸 자만이 없다면 ~ B () 만 호출됩니다. 그러나 가상 파괴자가 있으므로 첫 번째 ~ d ()가 호출되면 ~ b ().

힙에 할당 된 B 또는 D의 구성원은 명시 적으로 삭제하지 않으면 거래되지 않습니다. 그리고 그들을 삭제하면 그들의 소멸자도 호출 할 것입니다.

나는 왜 내 클래스의 파괴자가 부름을받지 않았는지 궁금했다. 그 이유는 해당 클래스의 정의를 포함하는 것을 잊어 버렸기 때문입니다 (#include "class.h"). 나는 "클래스 A"와 같은 선언 만 가지고있었습니다. 그리고 컴파일러는 그것에 만족했고 "delete"라고 부릅니다.

아니요. 포인터가 삭제됩니다. B의 소멸자에서 명시 적으로 삭제를 호출해야합니다.

클래스 A의 대상에 대한 소멸자는 해당 객체에 대해 삭제가 호출되는 경우에만 호출됩니다. 클래스 B의 소멸자에서 해당 포인터를 삭제하십시오.

삭제가 객체에서 호출 될 때 발생하는 일에 대한 자세한 내용은 다음을 참조하십시오.http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.9

아니오 클래스 A에 대한 Destructor를 호출하지 않으면 Poweroy와 같이 명시 적으로 호출해야합니다. 비교하는 예에서 ...

  #include <iostream>

  class A
  {
     public:
        A(){};
        ~A();
  };

  A::~A()
  {
     std::cout << "Destructor of A" << std::endl;
  }

  class B
  {
     public:
        B(){ptr = new A();};
        ~B();
     private:
        A* ptr;
  };

  B::~B()
  {
     delete ptr;
     std::cout << "Destructor of B" << std::endl;
  }

  int main()
  {
     B* b = new B();
     delete b;
     return 0;
  }

당신은 같은 것을 가지고 있습니다

class B
{
   A * a;
}
B * b = new B;
b->a = new A;

당신이 전화하면 전화하십시오 delete b;, 아무 일도 일어나지 않으며 메모리 누출이 있습니다. 기억하려고합니다 delete b->a; 좋은 해결책은 아니지만 다른 사람들이 있습니다.

B::~B() {delete a;}

이것은 a를 삭제하는 B의 소멸자입니다. (A가 0이면 삭제는 아무것도하지 않습니다. A가 0이 아니지만 새로부터 메모리를 가리키지 않으면 힙 손상이 발생합니다.)

auto_ptr<A> a;
...
b->a.reset(new A);

이런 식으로 당신은 포인터가 아니라 오히려 auto_ptr <> (shared_ptr <>도 다른 스마트 포인터도 할 것입니다), b가있을 때 자동으로 삭제됩니다.

이 방법 중 하나가 잘 작동하며 두 가지를 모두 사용했습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top