严格混叠规则对“包括上述类型之一的聚合或联合类型”的严格别名规则有什么影响?

gez*_*eza 3 c++ struct strict-aliasing language-lawyer

以前,在basic.lval中有以下要点:

集合或联合类型,在其元素或非静态数据成员(递归包括子集合或包含的联合的元素或非静态数据成员)中包括上述类型之一,

在当前草案中,它已消失。

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

7.2.1 [basic.lval]第10段的别名规则是从C改编而成,并增加了C ++。但是,许多要点要么不适用,要么被其他要点包含。例如,在C中需要为集合和联合类型提供结构分配,这在C ++中是通过C ++中的构造函数和赋值运算符完成的,而不是通过访问完整对象来完成的。

谁能告诉我,这是什么意思?这个严格的别名规则与C中的结构分配有什么关系?

cppreference对此规则说:

这些项目符号描述了C ++中不会出现的情况

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

struct Foo {
    float x;
};

float y;
float z = reinterpret_cast<Foo*>(&y)->x;
Run Code Online (Sandbox Code Playgroud)

最后一行似乎完成了项目要点描述的内容。它通过包含(成员)的集合访问y(a )。floatfloatx

谁能对此有所启发?

Mic*_*her 5

用于访问存储的值的左值y不是*reinterpret_cast<Foo*>(&y)type Foo,而是is reinterpret_cast<Foo*>(&y)->x,具有类型floatfloat使用类型的左值访问a float很好。在C ++中,您不能“访问联合或结构的值”(作为整体),只能访问单个成员。您引用的基本原理指出了C和C ++之间的区别:

  struct X { int a, b; };
  struct X v1 = {1, 2}, v2;
  v2 = v1;
Run Code Online (Sandbox Code Playgroud)

在C语言中,标准表示,赋值加载v1(整体)将其赋值给的值v2。在这里,对象v1.a和的值v2.b(都具有类型int)是使用类型的左值struct X不是 int)来访问的。

在C ++中,该标准表示该赋值调用编译器生成的赋值运算符,该运算符等效于

struct X {
   ...
   struct X& operator=(const struct X&other)
   {
       a = other.a;
       b = other.b;
   }
};
Run Code Online (Sandbox Code Playgroud)

在这种情况下,调用赋值运算符不会访问任何值,因为RHS是通过引用传递的。执行赋值运算符分别访问两个int字段(即使没有聚合规则也可以),因此这再次不会通过类型为lvalue的值访问struct X

  • 我同意这个答案,但是我认为问题中的一个不成文的假设是AB`“访问”“ A”(所以P-&gt; B`“访问”`* P`)。我没有在标准中看到任何明确指出并非如此的事实,但事实是,“ AB”本身并不意味着对任何事物的修改或从左值到右值的支持。 (3认同)