【发布时间】:2019-10-20 08:54:32
【问题描述】:
这里已经广泛讨论了通过reinterpret_casted 指针和相关的UB 访问对象。阅读问题和答案后,我仍然不确定是否正确使用 POD 类型的未初始化内存。
假设我想“模仿”
struct { double d; int i; };
通过手动为数据成员分配内存并假设(为简单起见)i 之前不需要填充。
现在,我这样做:
// (V1)
auto buff = reinterpret_cast<char*>(std::malloc(sizeof(double) + sizeof(int)));
auto d_ptr = reinterpret_cast<double*>(buff);
auto i_ptr = reinterpret_cast<int*>(buff + sizeof(double));
*d_ptr = 20.19;
*i_ptr = 2019;
第一个问题:这段代码有效吗?
我可以使用展示位置new:
// (V2)
auto buff = reinterpret_cast<char*>(std::malloc(sizeof(double) + sizeof(int)));
auto d_ptr = new(buff) double;
auto i_ptr = new(buff + sizeof(double)) int;
*d_ptr = 20.19;
*i_ptr = 2019;
我必须这样做吗?放置 new 在这里似乎是多余的,因为 POD 类型的默认初始化是无操作(空初始化),并且 [basic.life] 读取:
T类型对象的生命周期开始于:(1.1) 获得了
T类型的正确对齐和大小的存储,(1.2)如果对象有非空初始化,则其初始化完成,...
这是否表示 *d_ptr 和 *i_ptr 对象的生命周期在我为它们分配内存后开始?
第二个问题:我可以使用类型double*(或一些T*)作为buff,即
// (V3)
auto buff = reinterpret_cast<double*>(std::malloc(sizeof(double) + sizeof(int)));
auto d_ptr = reinterpret_cast<double*>(buff);
auto i_ptr = reinterpret_cast<int*>(buff + 1);
*d_ptr = 20.19;
*i_ptr = 2019;
或
// (V4)
auto buff = reinterpret_cast<double*>(std::malloc(sizeof(double) + sizeof(int)));
auto d_ptr = new(buff) double;
auto i_ptr = new(buff + 1) int;
*d_ptr = 20.19;
*i_ptr = 2019;
?
【问题讨论】:
-
@JesperJuhl,但我仍然想知道如果我真的必须要怎么做。
-
@supercat 什么......这甚至意味着什么以及它打算完成什么?
-
@supercat 我需要看到一些严肃的理由来证明编译器编写者不关心他们的客户会发现什么有用的想法。
-
@supercat 不知道这个例子是什么意思。
-
@Barry 在 supercat 的世界中,“质量编译器”是一种实现了他想到但从未能够成功表达的替代语言规范的编译器
标签: c++ language-lawyer c++17 placement-new