问题描述
int main()
{
Class_Name t;
Class_Name * p = &t;
delete p;
return 0;
}
这段代码在调用 2 个析构函数的情况下可以正常执行吗?删除如何处理堆栈对象?行为是否未定义?
This code executes fine with 2 destructors being called? How does delete work with stack objects? Is the behavior undefined?
推荐答案
您遇到了未定义的行为.
标准 (N3690) 5.3.5[expr.delete]
/2
Standard (N3690) 5.3.5[expr.delete]
/2
如果操作数具有类类型,则将操作数转换为指针通过调用上述转换函数来输入,然后使用转换后的操作数代替原始操作数本节的其余部分.在第一个选择(删除对象)中,delete 的操作数的值可能是一个空指针值,一个指向由前一个 new 表达式创建的非数组对象的指针,或指向表示此类基类的子对象 (1.8) 的指针对象(第 10 条).如果不是,则行为未定义.
...
If the operand has a class type, the operand is converted to a pointer type by calling the above-mentioned conversion function, and the converted operand is used in place of the original operand for the remainder of this section. In the first alternative (delete object), the value of the operand of delete may be a null pointer value, a pointer to a non-array object created by a previous new-expression, or a pointer to a subobject (1.8) representing a base class of such an object (Clause 10). If not, the behavior is undefined.
...
您没有空指针,也没有之前使用 new 分配的对象,因此行为未定义.
You don't have a null pointer, nor do you have an Object previously allocated with new, so the behavior is undefined.
注意:即使尝试做
int main()
{
Class_Name t;
t.~Class_Name()
return 0;
}
这将是未定义的行为.即使它没有删除,只是因为它显式调用具有自动存储持续时间的对象的析构函数.这意味着析构函数将被调用两次,一次是在显式调用时,第二次是在离开它的作用域时.
it would be undefined behavior. Even though it doesn't have a delete in it, simply because it explicitly calls the destructor of an Object with automatic storage duration. Which means that the destructor would be called twice, once when calling it explicitly, the 2nd time when leaving it's scope.
标准 12.4[class.dtor]
/15
一旦为一个对象调用了析构函数,该对象就不再存在;如果为某个对象调用析构函数,则行为未定义生命周期已结束的对象 (3.8).[ 示例:如果析构函数对于一个自动对象被显式调用,并且块是随后以通常会调用隐式的方式离开销毁对象,行为未定义.—结束示例 ]
Once a destructor is invoked for an object, the object no longer exists; the behavior is undefined if the destructor is invoked for an object whose lifetime has ended (3.8). [ Example: if the destructor for an automatic object is explicitly invoked, and the block is subsequently left in a manner that would ordinarily invoke implicit destruction of the object, the behavior is undefined. —end example ]
大多数情况下,尝试做这样的事情(希望如此)会导致崩溃.使用一个微不足道的解构器,你可能会有(坏)运气,但什么也没有发生.
Most of the time trying to do anything like that would (hopefully) lead to a crash. With a trivial deconstructor you might have (bad) luck and nothing happens though.
这里的小术语吹毛求疵:C++ 标准不谈论堆栈与堆对象,它总是分别谈论自动与动态存储持续时间.正如您在上面的引述中所见.
Little terminology nitpick here: The C++ standard doesn't talk about stack vs heap objects, it always talks about automatic vs dynamic storage duration respectively. As you can also see in the above quote.
您应该始终遵循一般准则:
- 对于堆栈分配的对象,不要进行任何显式的释放/删除(析构函数会自动调用).
- 对于每个
new
应该有一个对应的delete
- 对于每个
new[]
应该有一个对应的delete[]
- 对于每个
malloc
或calloc
都应该有一个对应的free
- For stack allocated objects don't do any explicit freeing/deleting (destructors get called automatically).
- For each
new
there should be a correspondingdelete
- For each
new[]
there should be a correspondingdelete[]
- For each
malloc
orcalloc
there should be a correspondingfree
这篇关于“删除"的行为是什么?与堆栈对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!