c++ 严格的别名、指针转换和std::launder

7ajki6be  于 2023-02-06  发布在  其他
关注(0)|答案(2)|浏览(186)

不幸的是,我对strict-aliasing规则和C/C++合法的强制转换后的解引用了解得太晚了。据我所知,下面的代码确实违反了上述规则:

std::byte buffer[sizeof(double)];
double* x = reinterpret_cast<double*>(buffer);

*x = 45.35;

是否允许以下列方式使用std::launder

std::byte buffer[sizeof(double)];
double* x = std::launder(reinterpret_cast<double*>(buffer));

*x = 45.35;

这样代码才是正确的?它是如何影响性能的?
那么,在C语言的某些扩展中做一些等价的事情是可能的(不使用联合或memcpy)?-fno-strict-aliasing选项是否使这种类型的强制转换更安全?

lp0sw83n

lp0sw83n1#

如果您通过mallocoperator new或类似函数分配了字节数组,则不需要launder,因为这些操作的结果是指向所创建对象的指针。然而,当直接处理字节数组变量时,需要launder来到达在该数组中创建的实际对象。
然而,这并不会导致对象 exist。而且在C20之前的隐式对象创建中,实际上没有对象存在。所以你的代码只能在C20的规则下工作(这些规则通过缺陷报告追溯到以前的标准,尽管只有更新的编译器才能将它们应用于旧标准下的编译)。

tkclm6bt

tkclm6bt2#

char buffer[sizeof(double)];
double* x = reinterpret_cast<double*>(buffer);

*x = 45.35;

这段代码很好,没有违反严格的别名规则。它做的完全一样,你可以自由地复制字节到/从字符。

相关问题