为什么左操作数所需的错误左值不会出现在字符串中?
why error lvalue required as left operand does not exhibit for strings?
在下面的代码片段中,为什么第 2 + 3 = 5
行语句出错但下一个分配给字符串连接的语句编译成功?
#include <string>
int main() {
2 + 3 = 5; // Error: lvalue required as left operand of assignment
std::string("2") + std::string("3") = std::string("5"); // Compiles successfully. why?
return 0;
}
我的理解是表达式 std::string("2") + std::string("3") = std::string("5")
的左侧会产生临时值 rvalue
。这意味着我要分配给 rvalue
- 就像 2 + 3 = 5
一样。所以它也应该给出 lvalue required as left operand of assignment
错误。但事实并非如此。
说明
对于class类型,赋值是通过复制和移动赋值运算符实现的。 std::string
是一个 class,所以
std::string("2") + std::string("3") = std::string("5")
只是
的语法糖
(std::string("2") + std::string("3")).operator=(std::string("5"))
operator=
是一个成员函数。通常,可以在左值和右值上调用成员函数。因此,这个表达式是有效的。
标准参考
对于非重载 operator=
(即对于 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 and return an lvalue referring to the left operand.
[...]
对于重载operator=
(对于std::string
):[expr.ass]/4
If the left operand is of class type, the class shall be complete.
Assignment to objects of a class is defined by the copy/move assignment operator ([class.copy], [over.ass]).
(所有人都强调我的)
该规则仅适用于内置类型的对象,例如 int
。
不适用于类。
该规则可能被认为对 类 的限制过于严格,其运算符可以重载以执行各种操作……或者可能在 C++ 出现时被认为过于严格,但它不会是好吧,也可以通过放宽内置函数的规则来破坏旧的 C 代码。
无论如何,加法的结果实际上是一个左值,因为当您 return 来自函数的 std::string&
之类的左值引用时,这就是您得到的结果。尽管事实上加法的两个操作数都是右值表达式和临时对象。这可能有点令人惊讶,there's a proposal to do better at "propagating value category" 在这种情况下,既然语言为我们提供了这样做的工具。
在下面的代码片段中,为什么第 2 + 3 = 5
行语句出错但下一个分配给字符串连接的语句编译成功?
#include <string>
int main() {
2 + 3 = 5; // Error: lvalue required as left operand of assignment
std::string("2") + std::string("3") = std::string("5"); // Compiles successfully. why?
return 0;
}
我的理解是表达式 std::string("2") + std::string("3") = std::string("5")
的左侧会产生临时值 rvalue
。这意味着我要分配给 rvalue
- 就像 2 + 3 = 5
一样。所以它也应该给出 lvalue required as left operand of assignment
错误。但事实并非如此。
说明
对于class类型,赋值是通过复制和移动赋值运算符实现的。 std::string
是一个 class,所以
std::string("2") + std::string("3") = std::string("5")
只是
的语法糖(std::string("2") + std::string("3")).operator=(std::string("5"))
operator=
是一个成员函数。通常,可以在左值和右值上调用成员函数。因此,这个表达式是有效的。
标准参考
对于非重载 operator=
(即对于 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 and return an lvalue referring to the left operand. [...]
对于重载operator=
(对于std::string
):[expr.ass]/4
If the left operand is of class type, the class shall be complete. Assignment to objects of a class is defined by the copy/move assignment operator ([class.copy], [over.ass]).
(所有人都强调我的)
该规则仅适用于内置类型的对象,例如 int
。
不适用于类。
该规则可能被认为对 类 的限制过于严格,其运算符可以重载以执行各种操作……或者可能在 C++ 出现时被认为过于严格,但它不会是好吧,也可以通过放宽内置函数的规则来破坏旧的 C 代码。
无论如何,加法的结果实际上是一个左值,因为当您 return 来自函数的 std::string&
之类的左值引用时,这就是您得到的结果。尽管事实上加法的两个操作数都是右值表达式和临时对象。这可能有点令人惊讶,there's a proposal to do better at "propagating value category" 在这种情况下,既然语言为我们提供了这样做的工具。