析构函数是否释放分配给它所属对象的内存,或者是否只是调用它,以便它可以在编译器释放对象之前执行最后一分钟的内务处理?
答案 0 :(得分:32)
'编译器'不会删除任何内容。它创建了在运行时执行操作的代码。
编写delete somePointer;
编译器时,实质上写道:
if ( has_virtual_destructor( * somePointer ) ) {
// virtual dispatch to a compiler-generated function
dynamic_cast< true_dynamic_type * >(somePointer)->destroy_dynamic_type();
/* contents of true_dynamic_type::destroy_dynamic_type() {
this->~true_dynamic_type();
operator delete( this); // executed within class context
} */
} else {
somePointer->~ClassName();
operator delete(somePointer);
}
换句话说,析构函数被调用,然后调用operator delete来释放存储空间。
如果析构函数是虚拟的,则使用虚拟调度以最派生的形式对对象执行整个操作。实现此目的的常用方法是向每个虚拟析构函数添加隐藏参数。
请注意,顶级if语句实际上并不是生成代码的一部分;编译器在编译时做出决定。
答案 1 :(得分:2)
调用析构函数以允许对象执行清理以及销毁对象本身已创建的任何其他对象。
操作系统将在完成析构函数后处理对象本身的释放。
答案 2 :(得分:0)
1)析构函数不属于对象,它属于类
2)它为类中的所有用户定义类型(类对象)调用析构函数。
3)清理是可选活动,仅在确实需要时才进行
答案 3 :(得分:0)
在析构函数退出之后并且在执行之前返回到“删除”调用或对象实例超出范围的点之前,将释放内存。从理论上讲,可以设置一个不同的内存管理器来处理new和delete,但这可能是默认行为的显式更改。
答案 4 :(得分:0)
更具体地说,除了程序员之外,没有人在C ++中释放内存。如果对象在堆栈上,则它驻留在程序的存储空间中,并在程序的生命周期中占用空间。如果它在堆上,那么创建该对象的人负责解除分配它。那是delete
做什么。这将我们带到析构函数 - 如果在类中创建对象,析构函数允许您在类离开作用域时删除它们。它可以让你“在离开时关灯”。
答案 5 :(得分:0)
析构函数自动调用被销毁对象的成员变量上的析构函数。那些析构函数可能会也可能不会释放内存。但是,指针没有析构函数,或者如果您愿意,指针的析构函数不执行任何操作。它没有释放它指向的内存。如果一个对象包含一个指向从“new”或“malloc”获得的对象的指针,则该对象的程序员可以使析构函数做正确的事情。如果内存在概念上是被破坏对象的一部分,则应该对析构函数进行编程以“删除”或“释放”内存。例如,“向量”对象通常从堆中获取内存,因为在编译时通常不知道所需的内存量。该内存在概念上是向量对象的一部分,因此向量类的程序员必须在析构函数中对其进行“删除”。像std :: vector这样的标准模板库可以正确地完成它。
另一方面,某些对象包含对其他对象的引用。字典或索引将包含对概念上不属于它们的对象的引用(指针)。析构函数不能释放该内存。 (如果您从电话簿中删除了电话号码,则不希望手机自动消失。)
有一些例外,新手最初不需要关注。一种是当对象及其容器被编程为使用引用计数时,引用的对象实际上不会被释放,直到引用它的最后一个对象允许它去。另一个例外是“放置新的”。