将const右值引用绑定到非const右值的合法性疑问
C++右值引用绑定的标准合规性解答
涉及的C++标准条款
[dcl.init.ref]/5:
5- 类型为“cv1 T1”的引用由类型为“cv2 T2”的表达式初始化,规则如下:
- (5.1) [..]
- (5.2) [..]
- (5.3) 否则,若初始化表达式
- (5.3.1) 是右值(非位域)或函数左值,且“cv1 T1”与“cv2 T2”引用兼容,或
- (5.3.2) [..]
则第一种情况中初始化表达式的值,第二种情况中转换的结果被称为转换后初始化器。若转换后初始化器是prvalue,其类型T4将被调整为“cv1 T4”([conv.qual]),并应用临时物化转换([conv.rval])。无论何种情况,引用都绑定到得到的glvalue(或合适的基类子对象)。
[expr.type]/2:
若prvalue最初的类型为“cv T”,其中T是无cv限定的非类、非数组类型,在进一步分析前,该表达式的类型将被调整为T。
疑问1:const int&& r1 = 0;的绑定合法性
这个绑定是合法的,你的理解偏差出在对[expr.type]/2适用范围的错误判断:
- 初始化表达式
0是int类型的prvalue,符合[dcl.init.ref]/(5.3.1)的触发条件(右值、const int与int引用兼容)。 - 根据[dcl.init.ref]/5的明确规则,转换后初始化器是prvalue时,需先将其类型
int调整为cv1 T4(即const int)。 - 这里要注意:[expr.type]/2的调整仅针对最初的prvalue类型,而经过[dcl.init.ref]/5调整后的
const int类型prvalue,不属于“最初的prvalue类型”范畴,因此不会被[expr.type]/2调整回int。 - 对
const int类型的prvalue应用临时物化转换后,得到的是const int类型的xvalue,r1(const int&&)与该xvalue的类型完全匹配,绑定合法。
疑问2:const int&& r2 = static_cast<int&&>(0);的绑定合法性
这个绑定同样合法,核心依据是引用兼容规则允许更强cv限定的引用绑定到弱cv限定的右值:
- 初始化表达式
static_cast<int&&>(0)是int类型的xvalue,满足[dcl.init.ref]/(5.3.1)的条件(右值、const int与int引用兼容)。 - 由于转换后初始化器是xvalue,无需临时物化转换,但引用绑定规则本身允许将cv限定更强的引用绑定到cv限定更弱的glvalue——这不会破坏const正确性,因为
const int&&只能读取绑定的对象,无法修改它。 - 引用兼容的定义本身就支持cv1是cv2的超集(即cv1包含cv2的所有限定),因此
const int&&绑定到int类型的xvalue完全符合标准,不需要额外的[conv.qual]转换,引用绑定的过程已经隐含了这种安全的cv限定提升。
内容的提问来源于stack exchange,提问作者mada
相关产品推荐
相关产品推荐

