“删除”的行为是什么,与堆栈对象? [英] What is the behavior of "delete" with stack objects?

查看:169
本文介绍了“删除”的行为是什么,与堆栈对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  int main()
{
Class_Name t;
Class_Name * p =& t;

delete p;
return 0;
}

这个代码执行正常,调用2个析构函数?如何删除与堆栈对象协同工作?

解决方案

您遇到了未定义的行为。 b
$ b

标准(N3690)5.3.5 [expr.delete] / 2



< blockquote>

如果操作数具有类类型,则通过调用上述转换函数将操作数转换为指针
类型,并使用
转换的操作数本节的
剩余部分的原始操作数。 在第一个选项(删除对象)中,
delete的操作数的值可以是空指针值,
指向由前一个new-expression创建的非数组对象的指针,或
a指向表示这种
对象的基类的子对象(1.8)的指针(第10条)。如果没有,则此行为未定义。

...


一个空指针,也没有一个对象以前分配新的,所以行为是未定义的。



注意:

  int main()
{
Class_Name t;
t。〜Class_Name()
return 0;
}

这将是未定义的行为。即使它没有删除它,只是因为它显式调用对象的析构函数自动存储持续时间。这意味着析构函数将被调用两次,一次明确调用它,第二次离开它的范围。



标准12.4 [类。 dtor] / 15


一旦对一个对象调用析构函数,对象不再
存在;如果为寿命结束(3.8)的
对象调用析构函数,行为是未定义的。 [示例:如果显式调用自动对象的析构函数
,并且块以
的方式通常调用对象的隐式
销毁,未定义。 - end example
]


大多数时间尝试这样做会导致崩溃。有了一个琐碎的解构函数,你可能有(坏的)运气,但没有发生任何事。



这里的小术语nitpick:C ++标准不谈论堆栈对象,总是谈论自动vs动态存储持续时间。






您应该始终遵循一般原则:




  • 对于堆栈分配的对象,不执行任何显式释放/删除操作(析构函数自动调用)。

  • 对于每个 new ,应有相应的 delete

  • 对于每个 new [] ,应该有相应的 delete []

  • 对于每个 malloc calloc ,应该有一个相应的 free


int main()
{
    Class_Name t;
    Class_Name * p = &t;

    delete p;
    return 0;
}  

This code executes fine with 2 destructors being called? How does delete work with stack objects? Is the behavior undefined?

解决方案

You're running into undefined behavior.

Standard (N3690) 5.3.5[expr.delete]/2

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.
...

You don't have a null pointer, nor do you have an Object previously allocated with new, so the behavior is undefined.

Note: Even when trying to do

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.

Standard 12.4[class.dtor]/15

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.

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.


You should always follow the general guideline:

  • For stack allocated objects don't do any explicit freeing/deleting (destructors get called automatically).
  • For each new there should be a corresponding delete
  • For each new[] there should be a corresponding delete[]
  • For each malloc or calloc there should be a corresponding free

这篇关于“删除”的行为是什么,与堆栈对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆