指向子类的指针上的 delete 是否调用基类析构函数?

我有一个 class A,它对其中一个字段使用堆内存分配。类 A 被实例化并存储为另一个类中的指针字段(class B

当我处理完 B 类的对象时,我调用 delete,我假设它调用析构函数... ... 但是这也调用 A 类的析构函数吗?

编辑:

从答案中,我认为(请编辑,如果不正确) :

  1. B 实例的 delete调用 B: : ~ B () ;
  2. 叫做 A::~A();
  3. 显式 A::~A 应该 delete所有堆分配的 A 对象成员变量;
  4. 最后,存储 B 类实例的内存块被返回到堆——当使用 新的时,它首先在堆上分配一个内存块,然后调用构造函数来初始化它,现在在调用所有析构函数来完成对象之后,驻留对象的块被返回到堆。
282362 次浏览

指针将被删除。您应该在 B 的析构函数中显式地调用对 A 的删除。

它的名字是“解构器”,而不是“解构器”。

在每个类的析构函数中,必须删除所有其他用 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 的实例将会泄漏内存,因为它分配了一个它不释放的 A 的实例(在这种情况下,C 甚至没有析构函数)。

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

在上面的示例中,每个 delete 和 delete []都是必需的。在我没有使用它的地方不需要删除(或者确实能够使用)。

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

你应该在 B 的析构函数中删除 A。

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;

只有当基类具有 Virtual 关键字时,才会调用析构函数。

如果没有虚析构函数,那么只能调用 ~ B ()。但是因为您有一个虚析构函数,所以首先调用 ~ D () ,然后调用 ~ B ()。

除非您显式地删除它们,否则堆上分配的 B 或 D 的任何成员都不会被释放。删除它们也会调用它们的析构函数。

如果您有一个通常的指针(A*) ,那么将不会调用析构函数(并且 A实例的内存也不会释放) ,除非您在 B的析构函数中显式地执行 delete。如果您想要自动销毁,请查看像 auto_ptr这样的智能指针。

类 A 对象的析构函数只有在对该对象调用 delete 时才会被调用。确保在类 B 的析构函数中删除该指针。

有关在对象上调用 delete 时会发生什么的更多信息,请参见: Http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.9

当对 new 分配的指针调用 delete 时,将调用指向的对象的析构函数。

A * p = new A;


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

不,它不会为 A 类调用析构函数,你应该明确地调用它(像 PowerRoy 告诉) ,删除行‘ delete ptr;’例如比较..。

  #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;,则 a 不会发生任何事情,并且存在内存泄漏。试图记住 delete b->a;不是一个好的解决方案,但是还有其他一些方法。

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

这是 B 的析构函数,它将删除 a (如果 a 为0,则该 delete 不执行任何操作。)。如果 a 不是0,但不指向 new 中的内存,则会出现堆损坏。)

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

这样,您就不会有一个 as 指针,而是 auto _ ptr < > (share _ ptr < > 也可以,或者其他智能指针) ,当 b 被删除时,它会自动删除。

这两种方法都很管用,我都用过。

我想知道为什么没有调用类的析构函数。原因是我忘记包含那个类的定义(# include“ class.h”)。我只有一个像“ class A”这样的声明,编译器对此很满意,让我调用“ delete”。