65,211
社区成员
发帖
与我相关
我的任务
分享
int a=1;//这个a是左值无疑吗?
int a;
a=1;
int *b;
*b=a;//这个*b是左值吗?
#include<iostream>
using namespace std;
struct A{
int m_i;
A(int i):m_i(i){}
A& operator=(int i){
m_i=i;
return *this;
}
A operator+(const A&other){
return A(m_i+other.m_i);
}
~A(){cout<<m_i<<endl;}
};
int main()
{
A a1(2);
A a2(3);
(a1+a2)=5;//这里的(a1+a2)是左值还是右值?
return 0;
}int a=1;//这个a是左值无疑吗?
这是一个变量定义,即初始化。它不是一个表达式,其中的 a 也不是表达式。所以无所谓左值、右值(左值、右值是表达式的属性)
*b=a;//这个*b是左值吗?
*b 是左值。(*b 是一个表达式,它是 *b=a 的子表达式)
这里的 = 是一个普通的赋值运算符。赋值运算符左侧必须是一个可修改的左值。
(a1+a2)=5;
(a1+a2) 是一个右值。
但这里的 = 不是一个普通的复制运算符。它是一个函数调用,因而对左值、右值的需求按函数调用处理,不服从赋值运算符的规则。
上式实际是:
(a1+a2).operator=(5)
对于成员函数调用,只要调用的对象(这里是 a1+a2 )可以绑定到一个虚拟的增加的参数 A& 上(注1: 注意这个增加的参数不是 this ,类型也与 this 类型不一致;注2: 可以通过在函数声明的参数表后增加 const ,将 func()const ,将这个增加的参数的类型改为 const A& ),就可以成功调用。
在成员函数调用时,增加的这个虚拟的 A& 的参数可以绑定到一个右值上(与通常的引用绑定规则不同)
这样, (a1 + a2) 可以绑定到 A& 上,因而函数调用是可以成功的。
[注,这个虚拟的增加的参数并不真实存在,只用于重载判决(overload resolution),即判断函数是否可被调用]
int i=3, j =2;
(i+j) = 6; // error
这里 (i+j) 是一个右值,赋值运算符是一个普通的复制运算符。由于赋值运算符需要左侧是一个可修改的左值,因而是不可以的。#include<iostream>
using namespace std;
struct A {
int m_i;
A(int i) :m_i(i) {}
A& operator=(int i) && = delete;
A& operator=(int i) &{
m_i = i;
return *this;
}
A operator+(const A&other) {
return A(m_i + other.m_i);
}
~A() { cout << m_i << endl; }
};
int main()
{
A a1(2);
A a2(3);
(a1 + a2) = 5; // 把右值引用版本的operator=删了就不行了
return 0;
}
具体懒得查了,大体上可以看成默认情况下那个隐藏参数是右值引用的,所以可以把prvalue传进去,而在函数内部就可以通过lvalue操作临时对象了。