删除对象

Nim*_*ima 5 c++ memory-management object

首先,当你想释放分配给C++对象的内存时,首选哪一个?显式调用析构函数还是使用delete?

Object* object = new Object(...);
...

delete object;
Run Code Online (Sandbox Code Playgroud)

要么

object->~Object();
Run Code Online (Sandbox Code Playgroud)

第二,delete运算符是否隐式调用析构函数?

Ton*_*ony 13

delete 隐式调用析构函数,你不需要(更准确地说:不应该)直接调用它.

析构函数永远不会释放对象占用的内存(它可能驻留在堆栈上,而不是堆上,并且对象无法知道 - 但是,析构函数将删除对象组件分配的任何内存).

为了释放堆上分配的对象的内存,您必须调用delete.

当您编写自己的类时,C++将提供一个默认的析构函数来释放组件对象(例如QString,您的类的成员)分配的内存,但是如果您在构造函数中显式分配内存(或其他资源),则一定要提供一个明确释放这些资源的析构函数.

关于你自己的类的另一个一般规则:如果你标记任何方法virtual,你的析构函数也应该是virtual(即使你依赖于默认的析构函数),以便为从你的派生类派生的任何类调用正确的析构函数.


CB *_*ley 7

我也不喜欢.

只有在将内存分配与对象生命周期分离时,才需要非常非常少地进行显式析构函数调用.如果实现自定义容器类,则可能需要它.

显式delete是一种合法的方法来销毁使用new表达式动态创建的对象,但在大多数应用程序代码中它应该是不必要的,因为它表示可能发生新的和删除之间可能不匹配的地方以及具有潜在异常安全问题的区域.

在对象生存期被约束到块的情况下,通常应首选局部变量,因为内存分配开销通常较低,并且对象将自动被正确清理,但是块退出.

{
    // ...
    Object object( ... );

} // object destructor run, however this block is exited.
Run Code Online (Sandbox Code Playgroud)

如果有某种原因不需要这样(例如对象具有过多的静态大小)或者它的生命周期不能与特定范围匹配,那么通常应该使用某种智能指针来管理对象的生命周期.标准C++中最基本的智能指针std::auto_ptr可用于块作用域动态分配的对象,但在复制和赋值时具有"令人惊讶"的行为.类似tr1::shared_ptr(或boost::shared_ptr)的东西是需要共享所有权的常见替代方案.

{
    std::auto_ptr<Object> object(new Object(...));
    // ...
} // *object destructor run, however this block is exited.
Run Code Online (Sandbox Code Playgroud)

  • 虽然我谦虚地建议将示例从auto_ptr更改为shared_ptr,以便不鼓励任何不熟悉其复杂性的人使用auto_ptr,但提及手动生命周期管理的危险是+1. (3认同)