我正在尝试了解引用初始化的方式。例如,让我们看一个典型的例子。
double val = 4.55;
const int &ref = val;
我可以想到上述代码段中发生的事情的两种可能性。
通常的解释如下:
这里是 int
类型的临时值(prvalue)具有值(value) 4
创建然后引用 ref
绑定(bind)到这个临时的(prvalue)int
对象而不是绑定(bind)到变量val
直接地。发生这种情况是因为变量的类型 val
右边是double
而在左侧,我们有一个对int
的引用强>。但是要将引用绑定(bind)到变量,类型应该匹配。此外,临时纯右值的生命周期得到延长。
我认为还有另一种可能发生的情况如下:
这里是 int
类型的临时值(prvalue)具有值(value) 4
被 build 。但是因为 const int &ref
需要一个 glvalue,目前我们有一个 prvalue,临时物化开始,因此 prvalue 被转换为一个 xvalue。然后引用ref
绑定(bind)到这个具体化的 xvalue(因为 xvalue 也是一个 glvalue)而不是绑定(bind)到变量 val
直接地。发生这种情况是因为变量的类型 val
右边是double
而在左侧,我们有一个对int
的引用强>。但是要将引用绑定(bind)到变量,类型应该匹配。此外,物化临时 xvalue 的生命周期得到延长。
我的问题是:
PS:我不是在寻找解决这个问题的方法。例如,我知道我可以简单地写:
const double &ref = val;
.我的目标是根据 C++11 和 C++17 标准了解正在发生的事情。
最佳答案
const int &ref = val;
中的
val
是左值,而不是纯右值。即使它被转换为纯右值,这也不意味着在 C++11 或 C++17 中创建一个临时值。在 C++17 中,情况并非如此,因为只有 prvalue-to-xvalue 转换(以及此处不相关的一些特殊情况)会创建一个临时值,而在 C++11 中 [conv.lval]/2说只有类类型的左值到右值转换会创建一个临时对象。
引用的初始化在 [dcl.init.ref] 中解释。
在 C++11 中,根据 [dcl.init.ref]/5.2.2,所有以前的案例都失败了通过初始化表达式的复制初始化创建并初始化目标类型的临时对象,并将引用绑定(bind)到该临时对象。在此复制初始化中,左值 val
被转换为 double
类型的纯右值,然后转换为 int
类型的纯右值,这些步骤都不是创建额外的临时对象。
在 C++17 中,所有情况都会失败,直到 [dcl.init.ref]/5.2.2 ,其中声明初始化表达式首先隐式转换为目标类型的纯右值,这并不意味着创建临时值,然后应用临时物化转换(prvalue-to-xvalue 转换)并将引用绑定(bind)到结果,即指代临时值的 xvalue。
最后总是只有一个临时的,根据 [dcl.init.ref] 中的规则创建的。
https://stackoverflow.com/questions/71806505/
相关文章:
c# - 使用 EF Core 按 Id 检索实体的通用方法
javascript - Vue 3 - "Failed to resolve component"
kubernetes - kubectl 等到 pod 消失(终止)
android - 我无法将 Android 项目从 Delphi 10.4 迁移到 Delphi
node.js - 如何在某个日期之前安装 Node 包及其依赖项?
ios - 什么时候在 ios 中选择 serialQueue 而不是并发队列
typescript - 类型错误 : Cannot find module 'firebase-f