gpt4 book ai didi

c++ - 默认构造函数表达式和左值

转载 作者:行者123 更新时间:2023-12-01 20:00:35 25 4
gpt4 key购买 nike

我和我的 C++ 同事遇到了一个奇怪的构造:

struct A { int i; };
void foo(A const& a);

int main() {
foo(A() = A{2}); // Legal
}

A() = A{2} 表达式完全让我们感到困惑,因为它似乎将 A{2} 分配给一个临时的、默认构造的对象。但请在编译器资源管理器中查看它( https://gcc.godbolt.org/z/2LsfSk )。它似乎是一个法律声明(受 GCC 9 和 Clang 9 支持),如下声明:

struct A { int i; };

int main() {
A() = A{2};
auto a = A() = A{3};
}

因此,在某些情况下,A() 似乎是左值。还是这里发生了其他事情?希望得到一些解释,最好是对 C++17 标准的引用。

<小时/>

更新:@Brian 发现这是 assigning to rvalue: why does this compile? 的重复项。但如果有人能在 C++ 标准中找到适当的引用资料,我将不胜感激。

最佳答案

A{} 始终是 [expr.type.conv] 的右值

1 A simple-type-specifier or typename-specifier followed by a parenthesized optional expression-list or by a braced-init-list (the initializer) constructs a value of the specified type given the initializer. If the type is a placeholder for a deduced class type, it is replaced by the return type of the function selected by overload resolution for class template deduction for the remainder of this subclause.
2 If the initializer is a parenthesized single expression, the type conversion expression is equivalent to the corresponding cast expression. Otherwise, if the type is cv void and the initializer is () or {} (after pack expansion, if any), the expression is a prvalue of the specified type that performs no initialization. Otherwise, the expression is a prvalue of the specified type whose result object is direct-initialized with the initializer. If the initializer is a parenthesized optional expression-list, the specified type shall not be an array type.

强调我的

这些工作之所以在这里起作用,标准中没有任何内容可以阻止它工作。

对于像 int 这样的内置类型,有 [expr.ass]/1

The assignment operator (=) and the compound assignment operators all group right-to-left. All require a modifiable lvalue as their left operand; their result is an lvalue referring to the left operand.

因此这会阻止您执行 int{} = 42;。不过,本节不适用于类(class)。如果我们查看 [class.copy.assign]没有任何内容表明需要左值,但第一段确实说明了

A user-declared copy assignment operator X​::​operator= is a non-static non-template member function of class X with exactly one parameter of type X, X&, const X&, volatile X&, or const volatile X&

这意味着

A{} = A{2};

实际上是

A{}.operator=(A{2})

在右值类对象上执行此操作是合法的,因为类的默认 operator = 没有ref-qualifier 来阻止在右值上调用它。如果添加

A& operator=(const A& a) & { i = a.i; }

A 而不是使用默认的赋值运算符

A{} = A{2};

将不再编译,因为 operator= 现在仅适用于左值。

关于c++ - 默认构造函数表达式和左值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59430613/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com