c++ - 使用 reinterpret_cast 访问类似“struct {double, int}”的对象的对象
问题描述
通过 ed 指针和相关的 UB 访问对象reinterpret_cast
已在此处进行了广泛讨论。阅读问题和答案后,我仍然不确定是否正确使用 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
对象的生命周期在我为它们分配内存后开始?
第二个问题:我可以使用 type double*
(或 some T*
) for 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;
?
解决方案
正如巴里在这里更好地陈述的那样,1&3 是 UB。简短的版本:这些代码段都不包含创建对象所需的任何语法。而且您无法访问不存在的对象的值。
那么,2和4有效吗?
#2 当且仅当alignof(double) >= alignof(int)
. 但它仅在创建 adouble
后跟 an的意义上有效int
。它不会以任何方式“模仿”那个无名的结构。结构可以有任意数量的填充,而在这种情况下,int
将立即跟随double
.
严格来说,#4 不起作用。buff
实际上并不指向新创建的double
. 因此,指针算术不能用于获取该 object 之后的字节。所以做指针算术会产生未定义的行为。
现在,我们正在谈论严格意义上的C++ 。很可能,每个编译器都会执行所有这四个(上面关于对齐的警告)。
推荐阅读
- mysql - 具有多个连接的 MySQL 查询在 React js App 中性能缓慢
- javascript - 规范化 TS 和 Babel 之间默认导入的正确方法是什么?
- docker - docker-compose 在 ECS 上运行
- python - id() 与 `is` 运算符。比较`id`s是否安全?相同的“id”是否意味着相同的对象?
- javafx - JavaFX - 使用 FXML load() 函数时出错
- linux - 反应项目设置 - npm 运行 webpack 问题
- r - 将一个数据框中的列合并到新的数据框中,并过滤
- java - 接口方法覆盖
- apache - 在不切换 DocumentRoot 的情况下为主页使用不同的目录
- android - 我在proguard规则中做错了什么?