我写了以下的例子:
#include <iostream>
volatile int&& bar()
{
return 1;
}
int main()
{
const int& i = bar(); //error: binding of reference to type 'const int'
//to a value of type 'volatile int' drops qualifiers
}
但如果我们用int
替换int&&
,它就可以正常工作:
#include <iostream>
volatile int bar()
{
return 1;
}
int main()
{
const int& i = bar(); //OK
}
这并不是很清晰。标准中所说的是 (8.5.3/5 [dcl.init.ref]
):
类型为 "cv1 T1" 的引用通过 "cv2 T2" 类型的表达式进行初始化,如下所示:
- 如果引用是左值引用且初始化表达式
是一个左值(但不是位域),"cv1 T1" 和 "cv2 T2" 兼容,或
具有类类型(i.e., T2 is a class type),其中 T1 与 T2 不相关, 并且可以转换为类型为 "cv3 T3" 的左值,其中 "cv1 T1" 和 "cv3 T3" 兼容 108 (通过枚举适用的转换函数(13.3.1.6)和 通过重载分辨率(13.3)选择最佳函数来选择此转换), 那么引用绑定到第一种情况下的初始化表达式左值, 并绑定到第二种情况下的转换结果左值(或在任一情况下, 绑定到对象的适当基类子对象)。
[...]
- 否则,引用应是左值对于非易失性 const 类型(即 cv1 应该是 const), 或者引用应该是右值引用。
在第一个示例中,我们有类型为 volatile int&&
的右值。而5/5 [expr]
说:
如果表达式最初具有类型 "T 的引用"(8.3.2、8.5.3),则在进一步分析之前将类型调整为 T。
因此,在本质上,我们有类型为 volatile int
的右值,而不是 volatile int&&
,这意味着这两个示例应以相同的方式工作。