为什么字符串不显示作为左操作数的错误左值?

问题描述 投票:3回答:2

在下面的代码片段中,为什么行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错误。但事实并非如此。

c++ assignment-operator rvalue
2个回答
2
投票

说明

对于类类型,分配是通过复制和移动分配运算符实现的。 std::string是一门课程,所以

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

[赋值运算符(=)和复合赋值运算符所有组从右到左。全部要求可修改的左值左操作数,并返回引用左操作数的左值。[...]

对于过载operator=(对于std::string):[expr.ass]/4

如果左操作数是类类型,则该类应是完整的。由复制/移动赋值运算符定义对类对象的赋值([class.copy],[over.ass])。

(所有人都强调我的意思)


1
投票

该规则仅适用于内置类型的对象,例如int

不适用于课程。

[该规则可能被认为对类来说过于严格,其运算符可以被重载以执行各种操作……或者也许在C ++出现时就被认为过于严格,但是通过这种方式破坏旧的C代码并不是很好的做法。也放宽了内置规则。

无论如何,加法的结果实际上是一个左值,因为这是从函数返回一个左值引用(如std::string&)时得到的。尽管事实是加法的两个操作数都是右值表达式和临时对象。在这种情况下,there's a proposal to do better at "propagating value category"可能有点令人惊讶,因为这种语言为我们提供了执行此操作的工具。

© www.soinside.com 2019 - 2024. All rights reserved.