删除未使用新表达式构建的对象实际上可以吗?

Is it practically OK to delete object not constructed using the new expression?

本文关键字:实际上 对象 未使用 表达式 构建 删除      更新时间:2023-10-16

,这可能不行。根据cppref:

如果表达式是其他任何东西,包括它是通过新表达的数组形式获得的指针,则该行为是未定义的。

将其抛在一边,实践中的以下代码是否正常(T是非阵列,并且假设new未替换(?

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

据说在cppref中

调用分配函数时,新表达通过 要求作为第一个参数的字节数,类型 std::size_t,这是非阵列t。

sizeof(T)

所以我想这可能还可以。但是,也有人说,由于C 14,

允许新的表达来进行或组合分配 通过可更换的分配功能。如果出现, 编译器可以提供存储,而无需致电 分配功能(这也允许优化未使用的 新表达(。在合并的情况下,由 新表达E1可以扩展以提供额外的存储空间 另一个新表达E2如果以下所有内容都是正确的:[...]

请注意,只有在新表达时才允许此优化 使用的,没有任何其他可以调用可更换分配功能的方法: delete[] new int[10];可以优化,但operator delete(operator new(10));不能。

我不太确定含义。那么,在C 14中可以吗?

我为什么要问这个问题?(source(

有时,内存分配和初始化无法在一个步骤中完成。您必须手动分配内存,做其他事情,然后初始化对象,例如,提供强大的例外安全性。在这种情况下,如果无法在结果指针上使用删除表达式,则必须手动不启用和划分,这很乏味。为了使事情变得更糟,如果采用新表达方式和手动方法,您必须跟踪每个对象使用的一个。

如果您具有p = new(p) T{};,则该代码具有明确定义的行为,假设没有自定义(DE(分配函数在播放中。(可以很容易地对付此类事情;这样做是作为读者的练习。(

规则是,您必须给非阵列delete一个指向由非阵列new创建的对象(或基类(带有虚拟破坏者(该对象的子对象或null指针(。随之而来的是您的代码做到这一点。

不需要非阵列 new是非安置形式的。不可能,因为您最好能够删除new(std::nothrow) int。这也是一个放置 new-expression ,即使人们通常并不意味着当他们谈论"安置新"时。

delete定义为导致呼叫deallocation函数(忽略省略案例,这在这里是无关紧要的,因为 new> new-expression 所调用的唯一分配函数不是可更换的全局分配功能(。如果您设置了这些内容,以便将无效的参数传递给该交易函数,那么您就会从中获得不确定的行为。但是这里通过正确的地址(如果使用大小的DealLocation函数,则可以通过正确的大小(,因此定义明确。

我没有完全掌握OP的最后一段。明确称击曲和然后处理指针的乏味是什么?这就是我所见过的任何stl和任何有信誉的自由。是的,您必须跟踪分配内存的方式,才能将其归纳。阅读std :: vector和/或std :: shared_ptr的API文档可以使一个正确的方法熟悉。如果您不熟悉explacit dtor呼叫的语法,则是一个简单的片段:

void * raw_ptr= my_alloc(sizeof(my_type),alignof(my_type));
if (!raw_ptr)
     throw my_bad_alloc();
my_type* ptr {new(raw_ptr) my_type{init_params}};
raw_ptr=nullptr;
    //...
ptr->~my_type();//hello! Is it me you're lookin' for?
if (!my_dealloc(ptr))
     throw my_runtime_error();
ptr=nullptr;