首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用reinterpret_cast访问"struct {double,int}"-like对象

使用reinterpret_cast访问"struct {double,int}"-like对象
EN

Stack Overflow用户
提问于 2019-06-05 03:50:46
回答 2查看 115关注 0票数 2

通过reinterpret_casted指针和相关的UB访问对象已经在这里进行了广泛的讨论。在阅读了问答之后,我仍然不确定如何正确使用POD类型的未初始化内存。

假设我想要“模仿”

代码语言:javascript
复制
struct { double d; int i; };

通过手动为数据成员分配内存,并假设(为简单起见)在i之前不需要填充。

现在,我这样做:

代码语言:javascript
复制
// (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;

第一个问题:这段代码有效吗?

我可以使用placement new

代码语言:javascript
复制
// (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;

非做不可吗?Placement new在这里似乎是多余的,因为POD类型的默认初始化是no-op (空初始化),并且basic.life读取:

T类型的对象的生命周期从以下情况开始:

(1.1)获得具有用于类型T的适当对准和大小的存储,

(1.2)如果对象具有非空初始化,则其初始化完成,...

这是不是说一旦我为*d_ptr*i_ptr对象分配了内存,它们的生命周期就开始了?

第二个问题:我可以为buff使用类型double* (或一些T*)吗?

代码语言:javascript
复制
// (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;

代码语言:javascript
复制
// (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;
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-06-05 08:42:42

作为巴里states better here,1和3是UB。简而言之:这些代码片段都不包含任何the syntax needed to create an object。你不能访问一个不存在的对象的值。

那么,2和4行得通吗?

#2当且仅当alignof(double) >= alignof(int)时有效。但它的工作原理是先创建一个double,然后再创建一个int。它不会以任何方式“模仿”这个无名结构。该结构可以有任意数量的填充,而在这种情况下,int将紧跟在double之后。

严格地说,#4是不起作用的。buff实际上并没有指向新创建的double。因此,指针算法cannot be used to get the byte after that object。因此,执行指针运算会产生未定义的行为。

现在,严格地说,我们正在谈论C++。在所有的可能性中,每个编译器都会执行所有这四个(带有上面关于对齐的警告)。

票数 5
EN

Stack Overflow用户

发布于 2019-06-05 03:58:47

当我看公开可用的草案时,http://eel.is/c++draft/basic.life引用是不同的,它说

类型为T的对象的生命周期从以下情况开始:

(1.1)获得用于类型T的具有适当对齐和大小的存储器,以及

(1.2)其初始化(如果有的话)完成(包括空初始化) (dcl.init),

由于没有对double变量进行vacuous初始化,因此我认为代码是不正确的,并且会调用未定义的行为。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56450444

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档