在等号左边就是左值吗? 临时变量在等号左边,算左值还是右值?

bndare 2016-07-01 09:37:52

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;
}

上面的main函数中,a1+a2构造了一个临时变量,它出现在等号左边。那么它到底算左值还是右值,还是别的?

...全文
733 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
fefe82 2016-07-01
  • 打赏
  • 举报
回复
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) 是一个右值,赋值运算符是一个普通的复制运算符。由于赋值运算符需要左侧是一个可修改的左值,因而是不可以的。
  • 打赏
  • 举报
回复
auto& a = 测试的表达式 变量 等等.. 能编译过去就是左值.
bluewanderer 2016-07-01
  • 打赏
  • 举报
回复
终于又能说话了... oTZ 更正,是没有引用修饰的成员函数可以用隐含参数绑定右值。 For non-static member functions declared without a ref-qualifier, an additional rule applies: —(5.3) even if the implicit object parameter is not const-qualified, an rvalue can be bound to the parameter as long as in all other respects the argument can be converted to the type of the implicit object parameter. [Note: The fact that such an argument is an rvalue does not affect the ranking of implicit conversion sequences (13.3.3.2). —end note]
iyomumx 2016-07-01
  • 打赏
  • 举报
回复
首先,左值右值针对的是表达式而不是变量或对象 其次,在 C++ 中早就不能通过是否能出现在等号左边来判断是否为左值了,在 C++11 标准出现后除了 glvalue/prvalue 还增加了 xvalue,判定方法更为复杂 参考 https://www.zhihu.com/question/28039779
wen_eric 2016-07-01
  • 打赏
  • 举报
回复
a1+a2构造了一个临时变量,是右值。
wen_eric 2016-07-01
  • 打赏
  • 举报
回复
是不是左值不是靠等号来区分,是依据能不能获取到它的引用或地址来区分。
D41D8CD98F 2016-07-01
  • 打赏
  • 举报
回复
C++17对 value category 有大改。我个人没理解错的话,在 C++17 ,等号左边的就只能是 glvalue (泛左值)了,特定情况下 prvalue 可以转换为 glvalue
bluewanderer 2016-07-01
  • 打赏
  • 举报
回复
更正,重载的=可以要求*左边*只能是右值不能是左值... oTZ
bluewanderer 2016-07-01
  • 打赏
  • 举报
回复
你重载运算符以后很多东西就已经变了。重载的=甚至可以要求右边只能是右值不能是左值。规则还是直接看不叫好,通过试得出结论的风险是很大的。
bluewanderer 2016-07-01
  • 打赏
  • 举报
回复
引用 5 楼 fefe82 的回复:
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) 是一个右值,赋值运算符是一个普通的复制运算符。由于赋值运算符需要左侧是一个可修改的左值,因而是不可以的。
他这里a1 + a2是绑给右值引用了。
#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操作临时对象了。

65,211

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧