xvalue何时可作为lvalue?临时对象赋值疑问及代码解析
临时对象赋值的规则与代码解析
先明确核心规则:
- 内置类型的纯右值无法作为内置赋值运算符的左操作数,也不能取地址;
- 用户自定义类型的临时对象(右值),只要其赋值运算符成员函数未被限定为仅左值调用,就可以被赋值。
下面逐个分析代码中的每一行:
失败行解析
int * p1 = &get_int();get_int()返回的是int类型的纯右值,C++标准禁止获取纯右值的地址——纯右值没有持久的存储位置,无法生成有效的指针,因此编译报错。type * p2 = &get_type();get_type()返回的是自定义类型的临时对象(纯右值),虽然它有临时存储,但标准禁止直接取临时对象的地址——临时对象的生命周期仅维持到当前表达式结束,取地址会导致指针指向已销毁的对象,编译器直接拦截这种风险操作。get_int() = int{1};
内置类型的赋值是内置操作符,标准明确规定右值不能作为内置赋值的左操作数,因为内置类型的右值是不可修改的,因此编译失败。
成功行解析
get_type() = type{1};
这里调用的是type类默认生成的成员赋值运算符(type& type::operator=(const type&))。类的成员函数默认不区分调用对象是左值还是右值,只要成员函数没有通过&后缀限定为仅左值调用,临时对象(右值)就可以调用它。
虽然这个赋值操作修改的临时对象会在表达式结束后立即销毁,实际中几乎没有实用价值,但语法上完全符合C++标准,因此可以正常编译运行。
扩展:禁止自定义临时对象赋值
如果想让自定义类型和内置类型保持一致,禁止临时对象被赋值,可以显式将赋值运算符限定为仅左值调用:
struct type { int x; type& operator=(const type&) & = default; // 加&限定仅左值可调用 };
此时get_type() = type{1};会像内置类型一样编译失败。
内容的提问来源于stack exchange,提问作者J M Wallace
相关产品推荐
相关产品推荐

