7.3.1 Lvalue-to-rvalue conversion
一个非函数、非数组类型T的泛左值可以被转换为纯右值:
如果T是不完全类型,则需要执行此转换的程序是非法的(
ill-formed)。如果T是非类类型,则所得纯右值的类型为去掉cv限定的T。
否则,所得纯右值的类型就是T本身。
当对表达式E执行左值到右值转换时,如果:
- (2.1) E不是潜在可求值,或者
- (2.2) 对E的求值会进一步导致对其潜在结果中的某个成员Eₓ求值,而该Eₓ所命名的变量x并未被odr-used([basic.def.odr])。
则不会访问引用对象中所包含的值。【示例:
1 | struct S { int n; }; |
泛左值的转换的结果由下列规则决定:
(3.1) 若T是
cv std::nullptr_t,结果为一个空指针常量。【注释:因为转换不会访问泛左值所引用的对象,所以即使T带有volatile限定([intro.wxecution])也不会产生副作用;并且该泛左值可以引用联合([class.union])中当前非活跃的成员。——注释结束】(3.2) 否则,若T为类类型,则此转换会以该泛左值为源,对结果对象执行拷贝初始化。
(3.3) 否则,若泛左值所引用的对象中包含无效的指针值([basic.stc.dynamic.deallocation],[basic.stc.dynamic.safety]),则行为由实现定义。
(3.4) 否则,读取([defns.access])泛左值所指示的对象,该对象中包含的值是纯右值。
Paw5zx个人理解:点击查看更多
- (3.1) 类型为std::nullptr_t的泛左值,到右值的转换结果就是空指针常量,转换过程不会访问任何对象也没有副作用
1 | std::nullptr_t np = nullptr; // np是左值 |
- (3.2) 类类型的泛左值,到右值的转换会调用拷贝/移动构造函数生成一个新的临时对象而不是直接按字节拷贝
1 | struct S |
- (3.3) 包含无效指针,行为由实现定义
- (3.4) 直接读内存值。
1 | double a = 3.14; |
【注释:也可参见[basic.lval]。——注释结束】
7.3.4 Temporary materialization conversion
类型为T的纯右值可以转换为类型为T的将亡值。此转换通过将临时对象作为结果对象来求值该纯右值(即计算这个纯右值的表达式),从而用该纯右值初始化一个类型为T的临时对象([class.temporary]),并产生一个表示该临时对象的将亡值。类型T必须是完全类型。【注释:若T是类类型(或其数组),它必须具有可访问且未删除的析构函数;见[class.dtor]。——注释结束】
【示例:
1 | struct X { int n; }; |
——示例结束】
Paw5zx个人理解:点击查看更多
临时物化是让原来的纯右值求值结果直接构造到一个对象上(返回对象)(而不是先求值,在拷贝到该对象上),这个对象在语义上是将亡值。
还是鸡巴得学临时对象
这就是之前的URVO?
1 | struct X { int n; }; |
X()是纯右值X().n需要访问成员n,要求有个对象触发临时物化,X()
①创建一个类型为T的临时对象
②用纯右值来初始化这个临时对象
③产生一个将亡值,它表示这个刚创建的临时对象