What happened to the quot;aggregate or union type that includes one of the aforementioned typesquot; strict aliasing rule?(“包含上述类型之一的聚合或联合类型发生了什么?严格的别名规则?)
问题描述
以前,在 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 {浮动 x;};浮动 y;float z = reinterpret_cast(&y)->x;
最后一行似乎与要点描述的一样.它通过一个聚合访问y
(一个float
),聚合包含一个float
(成员x
).>
有人能解释一下吗?
你用来访问 y
的存储值的左值不是 *reinterpret_cast
,属于 Foo
类型,但它是 reinterpret_cast
,其类型为 浮动代码>.使用
float
类型的左值访问 float
没问题.在 C++ 中,您不能访问联合或结构的值"(作为整体),您只能访问单个成员.您引用的基本原理指出了 C 和 C++ 之间的区别:
struct X { int a, b;};struct X v1 = {1, 2}, v2;v2 = v1;
在 C 中,标准规定赋值会加载 v1
的值(作为整体)以将其分配给 v2
.这里对象 v1.a
和 v2.b
(都具有 int
类型)的值使用 类型的左值访问struct X
(不是 int
).
在 C++ 中,标准说赋值调用编译器生成的赋值运算符,相当于
struct X {...结构X&运算符=(const struct X&other){a = 其他.a;b = 其他.b;}};
在这种情况下,调用赋值运算符不会访问任何值,因为 RHS 是通过引用传递的.并执行赋值运算符分别访问两个 int
字段(这很好,即使没有聚合规则),因此这又不是通过 struct X类型的左值访问值代码>.
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.
There is some background information at WG21's site: 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.
Can anyone explain to me, what this means? What has this strict aliasing rule to do with struct assignment in C?
cppreference says about this rule:
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;
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?
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;
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
).
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;
}
};
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
.
这篇关于“包含上述类型之一的聚合或联合类型"发生了什么?严格的别名规则?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:“包含上述类型之一的聚合或联合类型"发生了什么?严格的别名规则?
基础教程推荐
- 如何在不破坏 vtbl 的情况下做相当于 memset(this, ...) 的操作? 2022-01-01
- 如何“在 Finder 中显示"或“在资源管理器中显 2021-01-01
- 使用从字符串中提取的参数调用函数 2022-01-01
- 为什么语句不能出现在命名空间范围内? 2021-01-01
- Windows Media Foundation 录制音频 2021-01-01
- 从 std::cin 读取密码 2021-01-01
- 在 C++ 中循环遍历所有 Lua 全局变量 2021-01-01
- 如何使图像调整大小以在 Qt 中缩放? 2021-01-01
- 为 C/C++ 中的项目的 makefile 生成依赖项 2022-01-01
- 管理共享内存应该分配多少内存?(助推) 2022-12-07