到底怎么确定函数调用表达式的结果是左值还是右值?

《C++primer》(第五版)P129页中说道:赋值运算符的左侧运输对象必须是一个可修改的左值。_
还有很多人说:左值右值的判定是:看能否使用取地址运算符,能用的是左值。
P202说到:函数的返回类型决定函数调用是否是左值。调用一个返回引用的的函数得到左值,其他返回类型得到右值。
请看看下面的代码,为什么该函数调用可以被用在赋值符左侧,也可以使用取地址运算符?但是最后一个表达式却是错的,说是:非常量引用只能绑定到左值。
到底怎么确定函数调用表达式的结果是左值还是右值?
string shortStr(string s1, string s2)
{
return s1.size() <= s2.size() ? s1 : s2;
}
int main( )
{
string str1 = "abcd", str2 = "efghi";
shortStr(str1, str2) = "oooo"; //A
string *ps=&(shortStr(str1, str2)); //B
string &rs = shortStr(str1,str2); //C
system("pause");
return 0;
}

左值右值的形式区分(或者称语法区分)是能否用取地址&运算符;语义区分(即其本质涵义)在于表达式代表的是持久对象还是临时对象。

在VS2019上A能通过编译,B、C通不过
对于A,函数的返回值是一个右值string,右值调用成员函数是可以的,A的操作也就是调用了string的operator=()这个函数,这是语法允许的,这跟基本类型的赋值是不同的。
对于B、C,同A函数返回的是右值string。取地址&操作,以及给引用赋初值都需要一个左值,也就是能寻址的对象,右值是不能寻址的。
PS:左值和右值都可以调用成员函数,都能改变其值。但左值能寻址,右值不能。
PS的PS:左值、右值其实很难说清,标准也是在变的,主要还是要知道表达式得到的结果是什么,以及能对结果做哪些操作就可以了。左值、右值能帮助理解表达式的时候就用,帮助不了就丢。

左值就是变量,可被修改,右值可以是变量和常量

我用的是VS2017,以上代码均验证过,只有表达式C无法通过。

左值一般是可以对其进行引用的,也就是&+左值。右值不可以,像常量一般被用作右值

&是取地址符,&rs得到的是一个地址值,相当于是一个常量了所以不能被赋值,而ps是一个指针变量,用来存放地址值。