C++解释赋值中的花括号

C++ interpret the curly bracket in assignment?

本文关键字:解释 赋值 C++      更新时间:2023-10-16

我刚刚尝试使用这段代码,但不知怎么的,我的编译器发现它没有标记错误。

struct structA{
int x;
int y;
};
...
struct structA var;
var={1,2};

这在某种程度上起到了很好的作用。据我所知,{,}子句只允许作为聚合初始化。我应该如何在这里解释它?

在这种情况下,structA是一个聚合,因此允许这种形式的初始化。

聚合是一个数组或具有的类

  • 没有用户提供的、显式的或继承的构造函数([class.ctor])
  • 没有私有或受保护的非静态数据成员(条款[class.access])
  • 没有虚拟函数,也没有虚拟、私有或受保护的基类([class.mi])

所以这是允许的:

struct structA var = {1,2};

但您实际拥有的是赋值,这也是允许的(从C++11),因为您使用的是作为rhs的初始值设定项列表。

如果右操作数是支持的初始化列表

  • 如果表达式E1具有类类型,则语法E1={args…}生成一个对赋值运算符的调用,该调用以支持的init-list为参数,然后选择适当的赋值操作员遵循过载解决规则

这样的初始化只允许用于聚合,包括POD班

structA是POD(纯旧数据)。因此它不会产生错误。

如果您将structA更改为:

struct structA{
int x;
int y;
structA(int, int){} //user-defined constructor
};

它会产生错误。请参阅此。通过大括号进行的赋值称为什么?它能被控制吗?获取更多信息

请参阅;Builtin Direct Assignment";在这个页面上:

https://en.cppreference.com/w/cpp/language/operator_assignment

Builtin direct assignment
The direct assignment expressions have the form
lhs = rhs   (1) 
lhs = {}    (2) (since C++11)
lhs = { rhs }   (3) (since C++11)
For the built-in operator, lhs may have any non-const scalar type and rhs must be implicitly convertible to the type of lhs.
The direct assignment operator expects a modifiable lvalue as its left operand and an rvalue expression or a braced-init-list (since C++11) as its right operand, and returns an lvalue identifying the left operand after modification.
For non-class types, the right operand is first implicitly converted to the cv-unqualified type of the left operand, and then its value is copied into the object identified by left operand.
When the left operand has reference type, the assignment operator modifies the referred-to object.
If the left and the right operands identify overlapping objects, the behavior is undefined (unless the overlap is exact and the type is the same)
If the right operand is a braced-init-list
if the expression E1 has scalar type,
the expression E1 = {} is equivalent to E1 = T{}, where T is the type of E1.
the expression E1 = {E2} is equivalent to E1 = T{E2}, where T is the type of E1.

如果表达式E1具有类类型,则语法E1={args…}生成对赋值运算符的调用,该调用以支持的init列表为参数,然后根据重载解析规则选择适当的赋值运算符。请注意,如果某个非类类型的非模板赋值运算符可用,则它优先于E1={}中的复制/移动赋值,因为{}到非类是一种身份转换,它高于从{}到类类型的用户定义转换。