use*_*570 2 c++ language-lawyer implicit-conversion c++11 c++17
我想了解如何引用初始化。例如,我们看一个典型的例子。
double val = 4.55;
const int &ref = val;
Run Code Online (Sandbox Code Playgroud)
我可以想到上面代码片段中发生的事情的两种可能性。
通常的解释如下:
这里创建了一个带有值类型的临时(纯右值),然后将引用绑定到这个临时(纯右值)对象,而不是直接绑定到变量。发生这种情况是因为右侧变量的类型是,而左侧我们有一个引用。但是为了将引用绑定到变量,类型应该匹配。此外,临时纯右值的生命周期也得到了延长。int4refintvalvaldoubleint
我认为还有另一种可能发生的情况,如下:
这里创建了一个具有值类型的临时(纯右值)。但由于需要一个左值并且当前我们有一个纯右值,因此临时物化开始,因此纯右值被转换为xvalue。然后引用绑定到这个具体化的 xvalue(因为 xvalue 也是泛左值) ,而不是直接绑定到变量。发生这种情况是因为右侧变量的类型是,而左侧我们有一个引用。但是为了将引用绑定到变量,类型应该匹配。此外,物化临时 xvalue 的生命周期也延长了。int4const int &refrefvalvaldoubleint
我的问题是:
PS:我并不是在寻找解决这个问题的方法。例如,我知道我可以简单地写:
const double &ref = val;。我的目标是根据C++11和C++17标准了解正在发生的情况。
valinconst int &ref = val;是左值,而不是纯右值。即使它被转换为纯右值,这并不意味着在 C++11 或 C++17 中创建临时值。在 C++17 中,情况并非如此,因为只有纯右值到 xvalue 的转换(以及一些与此处不相关的特殊情况)会创建临时值,而在 C++11 [ conv.lval]/2中则表示仅对于类类型左值到右值的转换会创建一个临时值。
引用的初始化在 [dcl.init.ref] 中进行了解释。
在 C++11 中,所有先前的情况都会失败,因此根据[dcl.init.ref]/5.2.2,通过初始化表达式的复制初始化来创建和初始化目标类型的临时对象,并且引用绑定到那个临时的。在此复制初始化中,左值val先转换为 类型的纯右值double,然后转换为 类型的纯右值int,这两个步骤都不会创建额外的临时值。
在 C++17 中,所有情况都会失败,直到[dcl.init.ref]/5.2.2,它指出初始化表达式首先隐式转换为目标类型的纯右值,这并不意味着创建临时的,然后应用临时物化转换(纯右值到x值转换)并将引用绑定到结果,即引用临时值的x值。
最后总是有一个临时对象,即根据 [dcl.init.ref] 中的规则创建的临时对象。
| 归档时间: |
|
| 查看次数: |
284 次 |
| 最近记录: |