"aggregate or union type that includes one of the aforementioned types" 严格别名规则发生了什么变化?

What happened to the "aggregate or union type that includes one of the aforementioned types" strict aliasing rule?

之前,在 basic.lval 中,有这个要点:

an aggregate or union type that includes one of the aforementioned types among its elements or non-static data members (including, recursively, an element or non-static data member of a subaggregate or contained union),

在目前的draft,已经没有了

WG21 网站上有一些背景信息:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1359r0.html#2051:

The aliasing rules of 7.2.1 [basic.lval] paragraph 10 were adapted from C with additions for C++. However, a number of the points either do not apply or are subsumed by other points. For example, the provision for aggregate and union types is needed in C for struct assignment, which in C++ is done via constructors and assignment operators in C++, not by accessing the complete object.

谁能给我解释一下,这是什么意思?这个严格的别名规则与 C 中的结构赋值有什么关系?

cppreference 说到这条规则:

These bullets describe situations that cannot arise in C++

我不明白,为什么是真的。例如,

struct Foo {
    float x;
};

float y;
float z = reinterpret_cast<Foo*>(&y)->x;

最后一行似乎与要点所描述的相同。它通过聚合访问 y(一个 float),其中包括一个 float(成员 x)。

任何人都可以阐明这一点吗?

您用来访问 y 的存储值的左值不是 *reinterpret_cast<Foo*>(&y),类型 Foo,而是 reinterpret_cast<Foo*>(&y)->x,类型 float。使用 float 类型的左值访问 float 没问题。在 C++ 中,你不能 "access the value of a union or struct" (作为整体),你只能访问个别成员。您引用的基本原理指出了 ​​C 和 C++ 之间的区别:

  struct X { int a, b; };
  struct X v1 = {1, 2}, v2;
  v2 = v1;

在 C 中,标准表示赋值加载 v1 的值(整体)以将其赋值给 v2。这里对象 v1.av2.b 的值(都具有类型 int)是使用 struct X 类型的左值(即 not int).

在C++中,标准说赋值调用编译器生成的赋值运算符,相当于

struct X {
   ...
   struct X& operator=(const struct X&other)
   {
       a = other.a;
       b = other.b;
   }
};

在这种情况下,调用赋值运算符不会访问任何值,因为 RHS 是通过引用传递的。并且执行赋值运算符分别访问两个 int 字段(这很好,即使没有聚合规则),所以这又不是通过 struct X.[=28= 类型的左值访问值]