这真的违反了严格的混叠规则吗? [英] Does this really break strict-aliasing rules?

查看:81
本文介绍了这真的违反了严格的混叠规则吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

When I compile this sample code using g++, I get this warning:

警告:取消引用类型化指针会破坏严格混叠规则[-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别名,因此将其强制转换为int不会违反严格的别名规则?还是我在这里想念东西?

In this case, doesn't data alias an int, and therefore casting it back to an int would not violate strict aliasing rules? Or am I missing something here?

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

Strange, when I define data like this:

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

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

The compiler warning goes away. Does the stack allocation make a difference with strict aliasing? Does the fact that it's a char[] and not a char* mean it can't actually alias any type?

推荐答案

该警告绝对合理.指向data的衰减指针不会指向类型为int 的对象,并且对其进行强制转换也不会改变它.参见 [basic.life]/7 :

The warning is absolutely justified. The decayed pointer to data does not point to an object of type int, and casting it doesn't change that. See [basic.life]/7:

如果在对象的生存期结束之后且在存储之前 被占用的对象被重用或释放,一个新的对象是 在原始对象占用的存储位置创建, a 指向原始对象的指针,该参考引用了 到原始对象,或者原始对象的名称将 自动引用新对象,并且 新对象已启动,可用于操作新对象,如果:
(7.1)— [..]
(7.2)— 新对象的类型与 原始对象(忽略顶级简历限定符)

If, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, a new object is created at the storage location which the original object occupied, a pointer that pointed to the original object, a reference that referred to the original object, or the name of the original object will automatically refer to the new object and, once the lifetime of the new object has started, can be used to manipulate the new object, if:
(7.1) — [..]
(7.2) — the new object is of the same type as the original object (ignoring the top-level cv-qualifiers),

新对象不是char的数组,而是int的数组. P0137 ,指向的概念,添加launder:

The new object is not an array of char, but an int. P0137, which formalizes the notion of pointing, adds launder:

[注意:如果不满足这些条件,则指向新对象的指针 可以从代表其地址的指针获得 通过调用std::launder进行存储(18.6 [support.dynamic]). — 尾注 ]

[ Note: If these conditions are not met, a pointer to the new object can be obtained from a pointer that represents the address of its storage by calling std::launder (18.6 [support.dynamic]). — end note ]

即您的代码段可以通过以下方式得到纠正:

I.e. your snippet can be corrected thusly:

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

..或仅从放置new的结果初始化一个新指针,这也将删除警告.

.. or just initialize a new pointer from the result of placement new, which also removes the warning.

这篇关于这真的违反了严格的混叠规则吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆