C++ 删除指向子类的指针是否调用基类析构函数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/677653/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Does delete on a pointer to a subclass call the base class destructor?
提问by Nick Bolton
I have an class A
which uses a heap memory allocation for one of its fields. Class A is instantiated and stored as a pointer field in another class (class B
.
我有一个class A
使用堆内存分配为其字段之一。类 A 被实例化并存储为另一个类中的指针字段 ( class B
.
When I'm done with an object of class B, I call delete
, which I assume calls the destructor... But does this call the destructor of class A as well?
当我处理delete
完B 类的对象时,我调用,我假设它调用了析构函数……但这是否也调用了类 A 的析构函数?
Edit:
编辑:
From the answers, I take that (please edit if incorrect):
从答案中,我认为(如果不正确,请编辑):
delete
of an instance of B calls B::~B();- which calls
A::~A();
A::~A
shouldexplicitlydelete
all heap-allocated member variables of the A object;- Finally the memory block storing said instance of class B is returned to the heap - when newwas used, it first allocated a block of memory on heap, then invoked constructors to initialize it, now after all destructors have been invoked to finalize the object the block where the object resided is returned to the heap.
delete
B 的实例调用 B::~B();- 其中调用
A::~A();
A::~A
应该显式地显示delete
A 对象的所有堆分配的成员变量;- 最后,存储所述类 B 实例的内存块返回到堆中——当使用new时,它首先在堆上分配一块内存,然后调用构造函数来初始化它,现在在调用所有析构函数来完成对象之后对象所在的块返回到堆中。
回答by Eclipse
The destructor of A will run when its lifetime is over. If you want its memory to be freed and the destructor run, you have to delete it if it was allocated on the heap. If it was allocated on the stack this happens automatically (i.e. when it goes out of scope; see RAII). If it is a member of a class (not a pointer, but a full member), then this will happen when the containing object is destroyed.
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
In the above example, every delete and delete[] is needed. And no delete is needed (or indeed able to be used) where I did not use it.
在上面的例子中,每个 delete 和 delete[] 都是需要的。在我没有使用它的地方不需要删除(或者确实可以使用)。
auto_ptr
, unique_ptr
and shared_ptr
etc... are great for making this lifetime management much easier:
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
回答by Nick Bolton
When you call delete on a pointer allocated by new, the destructor of the object pointed to will be called.
当对 new 分配的指针调用 delete 时,将调用指向对象的析构函数。
A * p = new A;
delete p; // A:~A() called for you on obkect pointed to by p
回答by Sebastian Mach
It is named "destructor", not "deconstructor".
它被命名为“析构函数”,而不是“析构函数”。
Inside the destructor of each class, you have to delete all other member variables that have been allocated with new.
在每个类的析构函数中,您必须删除所有其他已分配为 new 的成员变量。
edit: To clarify:
编辑:澄清:
Say you have
说你有
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;
}
Allocating an instance of B and then deleting is clean, because what B allocates internally will also be deleted in the destructor.
分配 B 的一个实例然后删除是干净的,因为 B 内部分配的内容也会在析构函数中删除。
But instances of class C will leak memory, because it allocates an instance of A which it does not release (in this case C does not even have a destructor).
但是类 C 的实例会泄漏内存,因为它分配了一个它不会释放的 A 实例(在这种情况下 C 甚至没有析构函数)。
回答by sharptooth
If you have a usual pointer (A*
) then the destructor will not be called (and memory for A
instance will not be freed either) unless you do delete
explicitly in B
's destructor. If you want automatic destruction look at smart pointers like auto_ptr
.
如果您有一个通常的指针 ( A*
) 则不会调用析构函数(A
例如也不会释放内存),除非您delete
在 inB
的析构函数中显式执行。如果你想自动销毁,看看像auto_ptr
.
回答by corné
You should delete A yourself in the destructor of B.
您应该在 B 的析构函数中自己删除 A。
回答by Brian R. Bondy
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;
}
};
When you do:
当你这样做时:
B *pD = new D();
delete pD;
The destructor will be called only if your base class has the virtual keyword.
只有当您的基类具有 virtual 关键字时才会调用析构函数。
Then if you did not have a virtual destructor only ~B() would be called. But since you have a virtual destructor, first ~D() will be called, then ~B().
然后,如果您没有虚拟析构函数,则只会调用 ~B() 。但是因为你有一个虚拟析构函数,首先 ~D() 将被调用,然后 ~B() 将被调用。
No members of B or D allocated on the heap will be deallocated unless you explicitly delete them. And deleting them will call their destructor as well.
在堆上分配的 B 或 D 的任何成员都不会被释放,除非您明确删除它们。删除它们也会调用它们的析构函数。
回答by David Thornley
You have something like
你有类似的东西
class B
{
A * a;
}
B * b = new B;
b->a = new A;
If you then call delete b;
, nothing happens to a, and you have a memory leak. Trying to remember to delete b->a;
is not a good solution, but there are a couple of others.
如果您随后调用delete b;
,a 不会发生任何变化,并且您会发生内存泄漏。试图记住delete b->a;
并不是一个好的解决方案,但还有其他一些解决方案。
B::~B() {delete a;}
This is a destructor for B that will delete a. (If a is 0, that delete does nothing. If a is not 0 but doesn't point to memory from new, you get heap corruption.)
这是 B 的析构函数,它将删除 a。(如果 a 为 0,则删除操作不执行任何操作。如果 a 不为 0 但未从 new 指向内存,则会导致堆损坏。)
auto_ptr<A> a;
...
b->a.reset(new A);
This way you don't have a as a pointer, but rather an auto_ptr<> (shared_ptr<> will do as well, or other smart pointers), and it is automatically deleted when b is.
这样你就没有 a 作为指针,而是一个 auto_ptr<>(shared_ptr<> 也可以,或者其他智能指针),当 b 是时它会自动删除。
Either of these ways works well, and I've used both.
这两种方法中的任何一种都很好用,我两种都用过。
回答by Harri Luoma
I was wondering why my class' destructor was not called. The reason was that I had forgot to include definition of that class (#include "class.h"). I only had a declaration like "class A;" and the compiler was happy with it and let me call "delete".
我想知道为什么我的班级的析构函数没有被调用。原因是我忘记包含该类的定义(#include "class.h")。我只有一个像“A类”这样的声明;编译器对此很满意,让我称之为“删除”。
回答by RvdK
No. the pointer will be deleted. You should call the delete on A explicit in the destructor of B.
不,指针将被删除。您应该在 B 的析构函数中显式调用 A 上的删除。
回答by Kris Kumler
The destructor for the object of class A will only be called if delete is called for that object. Make sure to delete that pointer in the destructor of class B.
只有在为该对象调用 delete 时才会调用类 A 对象的析构函数。确保在 B 类的析构函数中删除该指针。
For a little more information on what happens when delete is called on an object, see: http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.9
有关在对象上调用 delete 时会发生什么的更多信息,请参阅:http: //www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.9