【发布时间】:2011-10-04 10:35:02
【问题描述】:
我已经创建了一个代码块,就像这样。
proc()
{
Z* z = new Z();
}
现在在方法 proc 中声明的指针将只在 proc 之前具有作用域。我想问一下 z 的 DTOR 什么时候会被自动调用。无论是控件从方法 proc 中出来还是我的应用程序关闭时。
【问题讨论】:
我已经创建了一个代码块,就像这样。
proc()
{
Z* z = new Z();
}
现在在方法 proc 中声明的指针将只在 proc 之前具有作用域。我想问一下 z 的 DTOR 什么时候会被自动调用。无论是控件从方法 proc 中出来还是我的应用程序关闭时。
【问题讨论】:
根本不会调用析构函数。 *z 使用的内存将被泄露,直到应用程序关闭(此时操作系统将回收您的进程使用的所有内存) .
为避免泄漏,您必须在某个时候调用delete,或者更好的是,使用智能指针。
【讨论】:
这是内存泄漏。您可能应该拥有的是:
void
proc()
{
Z z;
}
并跳过动态分配。如果一个对象的生命周期对应于 它的范围,你很少需要动态分配。
如果由于某种原因您确实需要动态分配(例如,因为
多态性),那么你应该使用某种智能指针;
std::auto_ptr 在这里工作得很好,像 scoped_ptr 这样的东西,如果你
拥有它们,可能会更好。
【讨论】:
unique_ptr 只是一个更新的auto_ptr;如果您知道永远不必支持较旧的编译器,则可以使用它。 scoped_ptr 的语义要有限得多,因为它不支持所有权转移。
这是 C++ 的基础之一。
动态分配
在您的情况下,Z 的内存分配和随后的构造函数调用将发生在 new:
Z* z = new Z();
销毁和内存释放的相反部分将发生在delete:
delete z;
但是由于您的代码没有它,内存释放将永远不会发生,而且您将丢失指针z,将来无法释放对象。 这是典型的内存泄漏。
声明
另一方面,如果你这样声明对象:
Z z;
内存分配和构造函数将在声明点立即调用,当对象的存在范围结束时(即在函数结束时)将自动调用析构函数并释放内存。
动态分配与声明
我不会讨论什么更好什么不是更好,而是提供以下链接的其中一篇文章的摘录:
与将数据加载到程序数据段的声明不同,动态分配在程序堆栈(专门分配给该程序的 RAM 区域)上创建新的可用空间。
仅供参考:Stack = Performance,但not always the best solution。
参考文献
【讨论】:
除非您将z 传递给delete,否则您将会发生内存泄漏。
【讨论】:
*z,则不应使用动态分配。正如 James Kanze 所写,只需使用 Z z;,当 proc() 返回时,该对象将为您销毁。
不会自动调用 DTOR。您应该使用“删除”关键字。
【讨论】:
Z 的析构函数不会被调用,除非你在代码中加入这样的一行:
delete z;
【讨论】:
当你使用 new 时,对象是在堆上分配的,堆是在你程序中的所有函数之间共享的,也就是说,你可以松散地说,堆分配对象的范围是你的程序,所以不需要删除对象,它将一直存在,直到您的程序退出。
【讨论】: