删除不是使用新表达式构造的对象实际上可以吗? [英] Is it practically OK to delete object not constructed using the new expression?

查看:106
本文介绍了删除不是使用新表达式构造的对象实际上可以吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

就目前而言,这可能不行.根据 cppref :

Pedantically, this may not be OK. As per cppref:

如果 expression 是其他任何东西,包括如果它是通过new-expression的数组形式获得的指针,则行为是不确定的.

If expression is anything else, including if it is a pointer obtained by the array form of new-expression, the behavior is undefined.

放在一边,下面的代码在实践中是否可以使用(T是非数组,并假定未替换new)?

Putting that aside, is the following code OK in practice (T is non-array, and assuming that new is not replaced)?

auto p = (T*)operator new(sizeof(T));
new(p) T{};
delete p;

据说,在 cppref 中,

在调用分配函数时,new表达式将传递 请求作为第一个参数的字节数,类型 std::size_t,对于非数组T恰好是sizeof(T).

When calling the allocation function, the new-expression passes the number of bytes requested as the first argument, of type std::size_t, which is exactly sizeof(T) for non-array T.

所以我想这可能还可以.但是,也有人说,自C ++ 14起,

So I guess this is probably OK. However, it is also said that since C++14,

允许新表达式消除或合并已分配的分配 通过可替换的分配功能.如果省略, 可以由编译器提供存储,而无需调用 分配函数(这还可以优化未使用的 new-expression).如果是合并,则由 可以扩展new-expression E1以为 如果满足以下所有条件,则为另一个new表达式E2:[...]

New-expressions are allowed to elide or combine allocations made through replaceable allocation functions. In case of elision, the storage may be provided by the compiler without making the call to an allocation function (this also permits optimizing out unused new-expression). In case of combining, the allocation made by a new-expression E1 may be extended to provide additional storage for another new-expression E2 if all of the following is true: [...]

请注意,只有在new-expressions为 而不是其他任何方法来调用可替换的分配函数: delete[] new int[10];可以优化,但是operator delete(operator new(10));不能.

Note that this optimization is only permitted when new-expressions are used, not any other methods to call a replaceable allocation function: delete[] new int[10]; can be optimized out, but operator delete(operator new(10)); cannot.

我不太清楚其中的含义.那么,在C ++ 14中可以吗?

I'm not quite sure of the implications. So, is this OK in C++14?

我为什么要问这个问题?(有时,内存分配和初始化无法一步完成. 您必须手动分配内存,执行其他操作,然后初始化对象, 例如,提供强大的例外安全性. 在这种情况下,如果不能在结果指针上使用delete表达式,则必须手动取消初始化和取消分配,这很繁琐. 更糟糕的是,如果同时使用新表达式和手动方法, 您必须跟踪每个对象使用哪个对象.

Sometimes, memory allocation and initialization cannot be done in a single step. You have to manually allocate the memory, do something else, and then initialize the object, e.g., to provide strong exception safety. In this case, if the delete expression cannot be used on the resulting pointer, you have to manually uninitialize and deallocate, which is tedious. To make things worse, in case both new expression and the manual method are employed, you have to track which one is used for each object.

推荐答案

如果您具有p = new(p) T{};,则此代码具有明确定义的行为,假定没有任何自定义(取消)分配功能在起作用. (可以很容易地对付这种事情;这样做是读者的一项练习.)

This code has well-defined behavior if you have p = new(p) T{};, assuming that no custom (de)allocation functions are in play. (It can be easily hardened against such things; doing so is left as an exercise for the reader.)

规则是必须给非数组delete指向由该对象的非数组new(或带有虚拟析构函数的基类)子对象创建的对象的指针,或空指针).更改之后,您的代码就会做到这一点.

The rule is that you must give non-array delete a pointer to an object created by a non-array new (or a base class (with virtual destructor) subobject of such an object, or a null pointer). And with that change your code does that.

不需要将非数组new设置为非放置形式.不可能,因为您最好能够删除new(std::nothrow) int.这也是一个 new-expression 展示位置,即使人们在谈论新展示位置"时通常不是这样.

There's no requirement that the non-array new be of a non-placement form. There can't be, since you'd better be able to delete new(std::nothrow) int. And that's a placement new-expression too, even though people don't usually mean that when they talk about "placement new".

delete被定义为导致对释放函数的调用(忽略省略号的情况,在此无关紧要,因为 new-expression 调用的唯一分配函数不是可替换的全局变量分配功能).如果您进行设置,以便它将无效的参数传递给该释放函数,那么您将得到未定义的行为.但是在这里它传递了正确的地址(如果使用了大小合适的释放函数,则传递了正确的大小),因此它定义明确.

delete is defined to result in a call to a deallocation function (ignoring the elision cases, which is irrelevant here because the only allocation function called by the new-expression is not a replaceable global allocation function). If you set things up so that it passes invalid arguments to that deallocation function, then you get undefined behavior from that. But here it passes the right address (and the right size if a sized deallocation function is used), so it's well-defined.

这篇关于删除不是使用新表达式构造的对象实际上可以吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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