为什么我们不能用右值易失性 int&&&初始化对 const int 的引用?
Why can't we initialize a reference to const int with an rvalue volatile int&&?
我已经编写了以下示例:
#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]
):
对类型"cv1T1"的引用由类型的表达式初始化"cv2 T2"如下:
--如果引用是左值引用,并且初始值设定项表达式
是一个左值(但不是位字段),"cv1T1"是与"cv2T2"或兼容的参考
具有类类型(即T2是类类型),其中T1不是与T2相关的引用,并且可以转换为类型为"cv3T3"的左值,其中"cv1T1"与"cv3 T3"108(通过列举适用的转换函数来选择此转换(13.3.1.6),并通过过载分辨率(13.3)选择最佳值),然后引用绑定到第一个中的初始值设定项表达式lvalue在第二种情况下转换为左值结果(或者,在任何一种情况下,都指向对象)。
[…]
--否则,引用应为对非易失性常量类型(即,cv1应为常量),或引用应为右值参考
在第一个例子中,我们有一个类型为volatile int&&
的右值。并且'otherwise'
的情况适用于这两个例子。但5/5 [expr]
说:
如果一个表达式最初具有"对T的引用"类型(8.3.2,8.5.3),在任何进一步分析之前,将类型调整为T
因此,本质上,我们有一个类型为volatile int
而不是volatile int&&
的右值,这意味着这两个例子将以相同的方式工作。
这两种情况的区别在于,在情况1中,引用直接绑定,而在情况2中,它不直接绑定(即引用绑定到临时;定义可以在[dcl.init.ref]
的最后一段中找到)。
直接绑定失败,因为T2是易失性限定的,而T1不是(在标准术语中,T1与T2不兼容)。
间接绑定之所以成功,是因为当从bar()
返回的引用初始化临时int
时,该临时不是volatile
。(临时的类型为cv1 T1)。
了解为什么案例1是直接绑定。首先,bar()
在这里是一个xvalue。参见CCD_ 14〃;调用返回类型为右值引用的函数的结果是xvalue";。
来自[dcl.init.ref]/5
:
- 如果引用是左值引用,并且初始值设定项表达式[是左值]或[具有类类型]
不适用:初始值设定项是一个xvalue(而不是lvalue),它是一个引用,因此没有类类型。
- 否则,引用应为非易失常量类型的左值引用(即,cv1应为常量),或者引用应为右值引用
这确实适用:const int &
是对非易失性常量类型的左值引用。沿着这棵树走下去:
如果初始值设定项表达式
- 是xvalue(但不是位字段)、类prvalue、数组prvalue或函数lvalue,并且"cv1 T1"是与"cv2 T2"兼容的引用,或者
- [另一个案例]
则在第一种情况下引用被绑定到初始值设定项表达式的值[…]
这确实适用,因为bar()
是一个x值。因此,引用绑定到xvalue,这被称为直接绑定,因为它没有绑定到临时绑定。
注:。所有标准参考均来自C++14(N3936)。由于DR1288,本节从C++11更改为。
- 'max'匹配'std::function<const int &(const int &, const int &)>'无过载
- 在C++中,如果"int a = 3; int* p = &a;",那么为什么不允许"const int* &pp = p",但允许"const int* const &pp = p"?
- 调用'myStud::myStud(int, const char [5], int, int, int)'没有匹配函数
- 返回对象时从'const DList<int>* const'到 'DList<int>*' [-fallowive] 的转换无效
- int(int)& 或 int(int) const &是什么类型?
- 传递 const int* 和 int* 时调用重载函数的不同版本(const int* const&/&&)
- 如何在构造函数中初始化int const * const
- 对"displayForStudent(int, int const*, double const*, int)"的未定义引用 collect2.exe:错误:ld 返回 1 个退出状态
- 如何在 C++ 中解释"const int *const & variable"
- 为什么"int & const" MSVC 编译得很好?
- const int const&和const int&in C++有什么区别?
- std::set<int * const> 不会编译
- " invalid operands of types 'int' and 'int* const'" 来自功能的错误,来自书
- std::initializer_list<int const> 不能从 std::initializer_list <int>构造
- 对'std::string Helper::ToString<int>(int const&)'的未定义引用
- 无法弄清楚 int[3][3] 和 int(* const)[3] 之间的区别
- const int* const fun(const int* const& p) const的含义;
- 为什么vector<int * const>是非法/不合逻辑的?
- 对 Stack<int>::p ush(int const&) 的未定义引用
- JsonCpp:未定义的对"Json::Value::operator[](int) const"的引用