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

C++ 为什么字符串不显示作为左操作数所需的错误左值?,c++,assignment-operator,rvalue,C++,Assignment Operator,Rvalue,在下面的代码段中,为什么行2+3=5语句出现错误,但下一个赋值到字符串串联的语句编译成功 #include <string> int main() { 2 + 3 = 5; // E

在下面的代码段中,为什么行
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;                                                                                                                                                 
}
#包括
int main(){
2+3=5;//错误:赋值的左操作数需要左值
std::string(“2”)+std::string(“3”)=std::string(“5”);//编译成功。为什么?
返回0;
}
我的理解是表达式
std::string(“2”)+std::string(“3”)=std::string(“5”)
的左侧将产生临时值,即
rvalue
。这意味着我将赋值给
rvalue
——就像
2+3=5
。因此,它还应该给出赋值的左操作数所需的
左值。但事实并非如此

解释 对于类类型,赋值由复制和移动赋值运算符实现
std::string
是一个类,所以

std::string("2") + std::string("3") = std::string("5")
只是语法上的糖

(std::string("2") + std::string("3")).operator=(std::string("5"))
operator=
是一个成员函数。通常,可以对左值和右值调用成员函数。因此,这个表达式是有效的

标准参考 对于非重载的
运算符=
(即对于
int
):

赋值运算符(
=
)和复合赋值运算符 从右向左分组。它们都需要一个可修改的左值作为它们的 左操作数并返回引用左操作数的左值。 [……]

对于重载
运算符=
(对于
std::string
):

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


(所有人都强调mine)

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

它不适用于课程

<> P>这个规则可能被认为是对类的限制太大,它的操作符可以被重载来做各种事情…或者在C++出现的时候被认为是限制性的,但是通过放松内置代码的规则来破坏旧的C代码是不正确的。
不管怎样,加法的结果实际上是一个左值,因为这是从函数返回左值引用(如
std::string&
时得到的结果。尽管加法的两个操作数都是右值表达式和临时对象,但情况仍然如此。这可能有点令人惊讶,在这种情况下,现在语言为我们提供了这样做的工具。

简化
std::string(“3”)=std::string(“5”)
仍然编译刚刚检查过的大多数标准容器的可能副本,其中非标准容器的右值版本为
运算符=
已删除,例如
基本字符串和基本字符串::运算符=(图表ch)&&&=delete操作。所以我想这是一个有意识的决定。更奇怪的是赋值返回的是左值,而不是x值。@DavisHerring-Yes。我要说的是,
std::string
最初不是为右值赋值而设计的,所以它不需要传播值类别。@L.F.它是我能做的所有std容器tell@UnSat:…它的标识和存储是临时物化的,用于为(隐式)函数调用生成xvalue对象表达式。但是说“它返回
std::string&
,所以它是一个左值”要容易得多。@UnSat这是关于值类别的简化视图。对于一些简单的场景,这可能是一个有用的类比,但不要将其视为一个定义。加法的结果(作为
操作符+
调用的
+
表达式)是一个右值。赋值的结果是一个左值。@aschepler-Hmm。我从来没有想过内置操作的规则会适用于过载的操作。事实上,我确信最近有一个案例,其中一条规则显然没有。我闻到不一致的味道,这不是在使用内置操作员的规则。添加两个字符串的结果是一个右值,因为使用的
运算符+
函数返回一个
std::string
(不是引用)。@aschepler。。。。哦,是的。