Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/142.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么可以';t我们用右值volatile int初始化对const int的引用&&;?_C++_Reference - Fatal编程技术网

C++ 为什么可以';t我们用右值volatile int初始化对const int的引用&&;?

C++ 为什么可以';t我们用右值volatile int初始化对const int的引用&&;?,c++,reference,C++,Reference,我编写了以下示例: #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 qua

我编写了以下示例:

#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
}

这还不清楚。标准所说的是(
8.5.3/5[dcl.init.ref]
):

类型“cv1 T1”的引用由类型为的表达式初始化 “cv2 T2”如下所示:

-如果引用是左值引用,则 初始值设定项表达式

  • 是左值(但不是位字段),“cv1 T1”是与“cv2 T2”兼容的引用,或

  • 具有类类型(即T2是类类型),其中T1与T2无关, 并且可以转换为“cv3 T3”类型的左值,其中“cv1 T1”与 “cv3 T3”108(通过列举适用的转换函数来选择此转换 (13.3.1.6),并通过过载分辨率(13.3)选择最佳,然后 引用绑定到第一个表达式中的初始值设定项表达式左值 第二种情况下转换的左值结果 (或者,在任何一种情况下,都是到 对象)

[……]

-否则,该引用应为对a的左值引用 非易失性常数类型(即cv1应为常数),或参考 应为右值参考

在第一个例子中,我们有一个类型为
volatile int&
的右值。而
“否则”
情况适用于这两个示例。但是
5/5[expr]
说:

如果表达式最初的类型为“引用T”(8.3.2, 8.5.3),在进一步分析之前,将类型调整为T


因此,本质上,我们有一个类型为
volatile int
的右值,而不是
volatile int&
,这意味着这两个示例将以相同的方式工作。

两种情况之间的区别是,在情况1中,引用直接绑定,而在情况2中,它不直接绑定(即,引用绑定到临时;定义可在
[dcl.init.ref]
的最后一段中找到)

直接绑定失败,因为T2是volatile限定的,而T1不是(在标准术语中,T1与T2不兼容)

间接绑定成功,因为当从
bar()
返回的引用初始化临时
int
时,临时的
volatile
(临时的类型为cv1 T1)


要了解为什么案例1是直接绑定。首先,
bar()
在这里是一个xvalue。请参见
[basic.lval]/1
“调用返回类型为右值引用的函数的结果是一个xvalue”

[dcl.init.ref]/5

  • 如果引用是左值引用且初始值设定项表达式[是左值]或[具有类类型]
不适用:初始值设定项是一个xvalue(不是左值),它是一个引用,因此没有类类型

  • 否则,该引用应为对非易失常数类型的左值引用(即,cv1应为常数),或该引用应为右值引用
这确实适用:
const int&
是对非易失性const类型的左值引用。沿着此树:

如果初始值设定项表达式

  • 是xvalue(但不是位字段)、类prvalue、数组prvalue或函数左值,且“cv1 T1”是与“cv2 T2”兼容的引用,或
  • [另一个案例]
然后,在第一种情况下,引用被绑定到初始值设定项表达式的值[…]

这确实适用,因为
bar()
是一个xvalue。因此,引用被绑定到xvalue,这称为直接绑定,因为它没有绑定到临时值



注意:所有标准引用都来自C++14(N3936)。由于DR1288,本节从C++11更改为。

此外,如果我没有弄错的话,在这种情况下返回的右值将是悬空引用,因为创建引用的温度在赋值i=bar()后立即被销毁;为什么不直接按值返回并让编译器优化(省略)或使用移动构造函数?@victor我相信他正在编写自己的编译器,因此需要理解第二个示例中的所有奇怪情况,bar()是一个prvalue;在第一个示例中,它是一个xvalue。不太清楚。如何区分它们?@DmitryFucintv
bar()
是一个xvalue,如果
bar
是一个返回右值引用的函数。请参见[basic.lval]/1我知道了。谢谢。你能提供一个引用描述吗?xvalues直接绑定到左值引用;prvalues没有。?
#include <iostream>

volatile int bar()
{
    return 1;
}

int main()
{
    const int& i = bar(); //OK

}