sk *_*tra 5 c++ memory stack memory-management
int main()
{
Class_Name t;
Class_Name * p = &t;
delete p;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这个代码执行正常,调用2个析构函数?delete如何使用堆栈对象?行为是否未定义?
use*_*027 12
您遇到了未定义的行为.
标准(N3690)5.3.5 [expr.delete]/ 2
如果操作数具有类类型,则通过调用上述转换函数将操作数转换为指针类型,并使用转换后的操作数代替本节其余部分的原始操作数.在第一个替代(删除对象)中,delete的操作数的值可以是空指针值,指向前一个新表达式创建的非数组对象的指针,或指向表示一个子对象的子对象(1.8)的指针.这种对象的基类(第10条).如果不是,则行为未定义.
...
您没有空指针,也没有先前使用new分配的Object,因此行为未定义.
注意:即使在尝试时也是如此
int main()
{
Class_Name t;
t.~Class_Name()
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这将是未定义的行为.即使它没有删除,只是因为它显式调用具有自动存储持续时间的Object的析构函数.这意味着析构函数将被调用两次,一次是在显式调用时,第二次是在离开它的范围时.
标准12.4 [class.dtor]/ 15
一旦为对象调用析构函数,该对象就不再存在; 如果为生命周期结束的对象调用析构函数,则行为未定义(3.8).[ 示例:如果显式调用自动对象的析构函数,并且该块随后以通常调用对象的隐式销毁的方式保留,则行为未定义.- 末端的例子 ]
大多数时候试图做这样的事情(希望)会导致崩溃.通过一个简单的解构函数,你可能会有(坏)运气,但没有任何反应.
这里的术语很少:C++标准没有谈论堆栈与堆对象,它总是分别讨论自动存储持续时间和动态存储持续时间.正如您在上面的引用中也可以看到的那样.
您应该始终遵循一般准则:
new应该有一个对应的deletenew[]应该有一个对应的delete[]malloc或calloc应该有一个相应的free