是否可以删除未使用新表达式构造的对象?

Lin*_*gxi 7 c++ new-operator dynamic-memory-allocation delete-operator c++14

小心翼翼,这可能不太好.根据cppref:

如果expression是其他任何东西,包括它是否是由new-expression的数组形式获得的指针,则行为是未定义的.

把它放在一边,实际上是下面的代码OK(T非数组,假设new没有替换)?

auto p = (T*)operator new(sizeof(T));
new(p) T{};
delete p;
Run Code Online (Sandbox Code Playgroud)

据说在cppref

当调用分配功能,新的表达通过请求作为第一个参数,类型的字节数 std::size_t,而这正是sizeof(T)对于非数组T.

所以我想这可能还行.但是,据说从C++ 14开始,

允许新表达式忽略或组合通过可替换分配函数进行的分配.在省略的情况下,存储器可以由编译器提供而不需要调用分配函数(这也允许优化掉未使用的new-expression).在组合的情况下,如果满足以下所有条件,则可以扩展由新表达式E1进行的分配以为另一个新表达式E2提供额外的存储:[...]

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

我不太确定其含义.那么,这在C++ 14中可以吗?

我为什么问这个问题?(来源)

有时,内存分配和初始化无法在一个步骤中完成.您必须手动分配内存,执行其他操作,然后初始化对象,例如,以提供强大的异常安全性.在这种情况下,如果删除表达式无法在结果指针上使用,则必须手动取消初始化和取消分配,这很乏味.更糟糕的是,如果使用新表达式和手动方法,则必须跟踪每个对象使用哪一个.

T.C*_*.C. 4

如果您有,则此代码具有明确定义的行为p = new(p) T{};,假设没有自定义(取消)分配函数在起作用。(它可以很容易地针对此类事情进行强化;这样做可以作为读者的练习。)

规则是,您必须为非数组提供delete一个指向由非数组创建的对象的指针new(或此类对象的基类(带有虚拟析构函数)子对象,或空指针)。通过这一更改,您的代码就可以做到这一点。

不要求非数组new是非放置形式。不可能有,因为你最好能够删除new(std::nothrow) int。这也是一种新的展示位置表达方式,尽管人们在谈论“新的展示位置”时通常并不是这个意思。

delete被定义为导致对释放函数的调用(忽略省略情况,这在这里无关紧要,因为 new 表达式调用的唯一分配函数不是可替换的全局分配函数)。如果您进行设置,使其将无效参数传递给该释放函数,那么您会从中得到未定义的行为。但这里它传递了正确的地址(如果使用了大小释放函数,则传递了正确的大小),因此它是明确定义的。

  • 直到最近几年,指针模型的全部含义才被真正完全理解。[有一篇论文正在进行中](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0813r0.pdf)来更改`construct`。@丹尼尔H (2认同)