C++类类型右值可赋值与左值引用绑定规则疑问
核心语法规则梳理
你遇到的所有差异本质上是C++对「右值的使用限制」分了三种独立的场景,规则互不重叠:
- 内置类型(标量)的右值,禁止作为赋值运算符的左操作数
- 类类型的右值,默认允许调用非const成员函数(包括编译器默认生成的赋值运算符)
- 非const左值引用,无论绑定目标是内置类型还是类类型,都只能绑定到左值,不能绑定到右值
逐个解答疑问
- 为什么
f5() = X(1)可以运行?f5()返回的是X类型的纯右值,赋值操作本质是调用成员函数:f5().operator=(X(1))。你没有自定义赋值运算符,编译器生成的默认拷贝赋值运算符没有加左值限定符,所以允许右值调用,代码合法。
如果想要禁止这种行为,可以给赋值运算符加左值引用限定:
X& operator=(const X&) & = default; // 仅允许左值调用赋值运算符
添加之后f5() = X(1)就会编译报错。
为什么
f() = 12无法运行?f()返回的是内置类型int的纯右值,C++语言层面直接规定内置类型的赋值运算符左操作数必须是可修改的左值,右值不能作为左操作数,所以直接报错,这是内置类型和类类型的规则差异。f7(f5())报错和右值属性冲突吗?
完全不冲突。f7的形参是X&类型的非const左值引用,C++明确规定非const左值引用只能绑定到同类型的左值,不能绑定到右值,这和右值是否能调用成员函数是完全独立的两条规则,没有任何关联。
如果想要让f7可以接收右值,可以把形参改成const X&(可以绑定到右值,但不能调用非const成员函数modify),或者改成X&&右值引用,就可以正常编译。关于
f6()相关的报错补充f6()返回的是const X类型的纯右值,哪怕是类类型的右值,加了const限定之后也不能调用非const成员函数,所以f6() = X(1)、f6().modify()都会报错,和前面的规则也完全匹配。
内容的提问来源于stack exchange,提问作者user16188058
相关产品推荐
相关产品推荐

