int main()
{
Class_Name t;
Class_Name * p = &t;
delete p;
return 0;
}
这段代码在调用 2 个析构函数时执行得很好?删除如何处理堆栈对象?行为是否未定义?
你遇到了未定义的行为。
标准(N3690)5.3.5[expr.delete]
/2
如果操作数具有类类型,则操作数将转换为指针
通过调用上述转换函数来类型化,并且
转换后的操作数用于代替原始操作数
本节的其余部分。在第一个替代方案(删除对象)中,
delete 操作数的值可以是空指针值,a
指向由先前的 new 表达式创建的非数组对象的指针,或者
指向代表此类基类的子对象 (1.8) 的指针
对象(第 10 条)。如果不是,则行为未定义。
...
您没有空指针,也没有先前用 new 分配的对象,因此行为未定义。
Note:即使在尝试做的时候
int main()
{
Class_Name t;
t.~Class_Name()
return 0;
}
这将是未定义的行为。即使它没有删除,只是因为它显式调用具有自动存储持续时间的对象的析构函数。这意味着析构函数将被调用两次,一次是在显式调用它时,第二次是在离开它的作用域时。
标准12.4[class.dtor]
/15
一旦为对象调用析构函数,该对象就不再
存在;如果为某个对象调用析构函数,则行为未定义
生命周期已结束的对象 (3.8)。 [示例:如果析构函数
对于自动对象被显式调用,并且该块是
随后以通常会调用隐式的方式离开
对象被破坏时,行为是未定义的。 —结束示例 ]
大多数时候,尝试做类似的事情(希望)会导致崩溃。对于一个微不足道的解构函数,你可能会运气不好,但什么也不会发生。
这里有一些术语挑剔:C++ 标准不讨论堆栈和堆对象,它总是分别讨论自动存储持续时间和动态存储持续时间。正如您在上面的引用中也可以看到的那样。
您应该始终遵循一般准则:
- 对于堆栈分配的对象,不要执行任何显式释放/删除(析构函数会自动调用)。
- 对于每个
new
应该有一个对应的delete
- 对于每个
new[]
应该有一个对应的delete[]
- 对于每个
malloc
or calloc
应该有一个对应的free
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)