“包括上述类型之一的集合或联合类型"发生了什么?严格的别名规则? [英] What happened to the "aggregate or union type that includes one of the aforementioned types" strict aliasing rule?

查看:81
本文介绍了“包括上述类型之一的集合或联合类型"发生了什么?严格的别名规则?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Previously, in basic.lval, there was this bullet point:

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

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),

在当前的草稿中,它不见了.

In the current draft, it is gone.

WG21网站上有一些背景信息:

There is some background information at WG21's site: 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 ++中的构造函数和赋值运算符完成的,而不是通过访问完整的对象来完成的.

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中的结构分配有什么关系?

Can anyone explain to me, what this means? What has this strict aliasing rule to do with struct assignment in C?

cppreference 谈到此规则:

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

These bullets describe situations that cannot arise in C++

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

I don't understand, why it is true. For example,

struct Foo {
    float x;
};

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

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

The last line seems to do what the bullet point describes. It accesses y (a float) through an aggregate, which includes a float (member x).

任何人都可以对此有所了解吗?

Can anyone shed some light on this?

推荐答案

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

The lvalue you use to access the stored value of y is not *reinterpret_cast<Foo*>(&y), of type Foo, but it is reinterpret_cast<Foo*>(&y)->x, which has the type float. Accessing a float using an lvalue of type float is fine. In C++, you can not "access the value of a union or struct" (as whole), you can only access individual members. The rationale you quoted points to a difference between C and 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)访问.

In C, the standard says that the assignment loads the value of v1 (as whole) to assign it to v2. Here the values of the objects v1.a and v2.b (both have types int) are accessed using an lvalue of type struct X (which is not int).

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

In C++, the standard says that the assignment calls the compiler generated assignment operator which is equivalent to

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

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

In this case, calling the assignment operator does not access any value, because the RHS is passed by reference. And executing the assignment operator accesses the two int fields separately (which is fine, even without the aggregate rule), so this is again not accessing a value through an lvalue of type struct X.

这篇关于“包括上述类型之一的集合或联合类型"发生了什么?严格的别名规则?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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