使用 reinterpret_cast 访问类似 "struct {double, int}" 的对象
Object access using reinterpret_cast for "struct {double, int}"-like object
通过 reinterpret_cast
ed 指针和相关 UB 访问对象已在此处进行了广泛讨论。阅读问题和答案后,我仍然不确定如何正确使用 POD 类型的未初始化内存。
假设我想"emulate"
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 类型的默认初始化是 no-op(空初始化),而 [basic.life] 读取:
The lifetime of an object of type T
begins when:
(1.1) storage with the proper alignment and size for type T
is obtained,
(1.2) if the object has non-vacuous initialization, its initialization is complete, ...
这是否表示 *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;
?
当我查看公开可用的草稿时,http://eel.is/c++draft/basic.life 引用不同,它说
The lifetime of an object of type T begins when:
(1.1) storage with the proper alignment and size for type T is obtained, and
(1.2) its initialization (if any) is complete (including vacuous initialization) ([dcl.init]),
由于没有 vacuous
双变量的初始化,我认为代码不正确并且调用了未定义的行为。
作为巴里 , 1&3 are UB. The short version: none of those pieces of code contain any of the syntax needed to create an object。而且您无法访问不存在的对象的值。
那么,2 和 4 行得通吗?
#2 当且仅当 alignof(double) >= alignof(int)
时有效。但它仅在创建 double
后跟 int
的意义上有效。它不会以任何方式"emulate"那个无名结构。该结构可以有任意数量的填充,而在这种情况下,int
将紧跟在 double
.
之后
#4 严格来说是行不通的。 buff
实际上并不指向新创建的double
。因此,指针运算 cannot be used to get the byte after that object。所以做指针运算会产生未定义的行为。
现在,我们谈论的是 C++ 严格来说。很有可能,每个编译器都会执行所有这四个(上面关于对齐的警告)。
通过 reinterpret_cast
ed 指针和相关 UB 访问对象已在此处进行了广泛讨论。阅读问题和答案后,我仍然不确定如何正确使用 POD 类型的未初始化内存。
假设我想"emulate"
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 类型的默认初始化是 no-op(空初始化),而 [basic.life] 读取:
The lifetime of an object of type
T
begins when:(1.1) storage with the proper alignment and size for type
T
is obtained,(1.2) if the object has non-vacuous initialization, its initialization is complete, ...
这是否表示 *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;
?
当我查看公开可用的草稿时,http://eel.is/c++draft/basic.life 引用不同,它说
The lifetime of an object of type T begins when:
(1.1) storage with the proper alignment and size for type T is obtained, and
(1.2) its initialization (if any) is complete (including vacuous initialization) ([dcl.init]),
由于没有 vacuous
双变量的初始化,我认为代码不正确并且调用了未定义的行为。
作为巴里
那么,2 和 4 行得通吗?
#2 当且仅当 alignof(double) >= alignof(int)
时有效。但它仅在创建 double
后跟 int
的意义上有效。它不会以任何方式"emulate"那个无名结构。该结构可以有任意数量的填充,而在这种情况下,int
将紧跟在 double
.
#4 严格来说是行不通的。 buff
实际上并不指向新创建的double
。因此,指针运算 cannot be used to get the byte after that object。所以做指针运算会产生未定义的行为。
现在,我们谈论的是 C++ 严格来说。很有可能,每个编译器都会执行所有这四个(上面关于对齐的警告)。