c++ - 刪除調用析構函數嗎?




6 Answers

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_ptrunique_ptrshared_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)為其中一個字段使用堆內存分配。 類A被實例化並作為指針字段存儲在另一個類(B)中。

當我完成對象B時,我打電話給刪除,我認為這是調用析構函數......但是這是否也調用類A中的析構函數?

編輯:

從答案中可以看出(如果不正確,請修改):

  1. delete B實例B調用B ::〜B();
  2. 它調用A::~A();
  3. and A::~A 應該明確地delete and A::~A所有堆分配成員變量;
  4. 最後將存儲所述B實例的內存塊返回給堆 - 當使用new時,它首先在堆上分配一塊內存,然後調用構造函數對其進行初始化,現在在調用所有析構函數完成對象之後將對象所在的塊返回給堆。



它被命名為“析構函數”,而不是“解構函數”。

在每個類的析構函數內部,你必須刪除已經用new分配的所有其他成員變量。

編輯:澄清:

假設你有

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的實例會洩漏內存,因為它分配了一個它不會釋放的實例(在這種情況下,C甚至沒有析構函數)。




你應該在B的析構函數中刪除A。




我想知道為什麼我的類的析構函數沒有被調用。 原因是我忘記了包含該類的定義(#include“class.h”)。 我只有一個像“A級”的聲明 編譯器很高興,讓我稱之為“刪除”。







你有類似的東西

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

如果你然後調用delete b; ,沒有任何事情發生,並且你有內存洩漏。 試著記住delete b->a; 不是一個好的解決方案,但還有其他一些。

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

這是B的一個析構函數,它將刪除一個。 (如果a是0,那麼這個刪除就不會執行任何操作。如果a不是0,但是不指向新的內存,則會導致堆損壞。)

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

這樣你就沒有一個指針了,而是一個auto_ptr <>(shared_ptr <>也可以,或者其他智能指針),並且它在b被自動刪除時被自動刪除。

這兩種方式都很好,而且我都用過。




Related