首页 文章

这真的打破了严格别名规则吗?

提问于
浏览
29

当我使用g编译此示例代码时,我收到此警告:

警告:解除引用类型惩罚指针将破坏严格别名规则[-Wstrict-aliasing]

代码:

#include <iostream>

int main() 
{
   alignas(int) char data[sizeof(int)];
   int *myInt = new (data) int;
   *myInt = 34;

   std::cout << *reinterpret_cast<int*>(data);
}

在这种情况下, data 是否为别名,因此将其强制转换为int不会违反严格的别名规则?或者我在这里遗漏了什么?

编辑:奇怪,当我像这样定义 data 时:

alignas(int) char* data = new char[sizeof(int)];

编译器警告消失了 . 堆栈分配是否与严格别名产生差异?事实上它是 char[] 而不是 char* 意味着它实际上不能为任何类型别名?

2 回答

  • -3

    警告是绝对合理的 . 指向 data 的衰减指针执行 not point to an object of type int ,并且转换它不会改变它 . 见[basic.life]/7

    如果在对象的生命周期结束之后并且在重用或释放对象占用的存储之前,在原始对象占用的存储位置创建新对象,指向原始对象的指针,引用引用原始对象,或者原始对象的名称将自动引用新对象,并且一旦新对象的生命周期开始,就可以用来操纵新对象,如果:(7.1) - [ . . ](7.2) - 新对象与原始对象的类型相同(忽略顶级cv限定符),

    新对象不是 char 的数组,而是 int . P0137,它正式化了指向的概念,增加了 launder

    [注意:如果不满足这些条件,可以通过调用std :: launder(18.6 [support.dynamic])从表示其存储地址的指针获取指向新对象的指针 . - 结束说明]

    即你的片段可以这样纠正:

    std::cout << *std::launder(reinterpret_cast<int*>(data));
    

    ..或者只是从placement new的结果中初始化一个新指针,这也会删除警告 .

  • 19

    改变怎么样?

    std::cout << *reinterpret_cast<int*>(data);
    

    int *tmp   = reinterpret_cast<int*>(data);
    std::cout << *tmp;
    

    在我的情况下,它摆脱了警告 .

相关问题