为什么我们不能用右值 volatile int&& 初始化对 const int 的引用?

2024-01-01

我写了下面的例子:

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

DEMO http://coliru.stacked-crooked.com/a/b54a5c0f73a3f559

但如果我们更换int&& with int它工作正常:

#include <iostream>

volatile int bar()
{
    return 1;
}

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

}

DEMO http://coliru.stacked-crooked.com/a/87b7778545007a7e

这还不太清楚。标准所说的是(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 的左值引用 非易失性 const 类型(即 cv1 应为 const),或引用 应为右值引用。

好吧,在第一个示例中,我们有一个类型的右值volatile int&&。还有'otherwise'case 适用于这两个示例。但5/5 [expr] says:

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

所以,本质上我们有一个类型的右值volatile int代替volatile int&&,这意味着这两个示例应以相同的方式工作。


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

直接绑定失败的原因是T2是 volatile 限定的并且T1不是(在标准术语中,T1 is not 参考兼容 with T2).

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


看看为什么案例 1 是直接绑定。首先,bar() is an xvalue这里。看[basic.lval]/1“调用返回类型为右值引用的函数的结果是 xvalue”。

From [dcl.init.ref]/5:

  • 如果引用是左值引用并且初始化表达式 [是左值] 或 [具有类类型]

不适用:初始化器是一个xvalue(不是lvalue),并且它是一个引用,因此它没有类类型。

  • 否则,该引用应为非易失性 const 类型的左值引用(即 cv1 应为 const),或者该引用应为右值引用

这确实适用:const int &是对非易失性 const 类型的左值引用。下这棵树:

如果初始化表达式

  • 是 xvalue(但不是位域)、类纯右值、数组纯右值或函数左值,并且“cv1 T1”与“cv2 T2”引用兼容,或者
  • [另一个案例]

那么在第一种情况下,引用将绑定到初始化表达式的值 [...]

这确实适用,因为bar()是一个 x 值。因此引用绑定到 x 值,这称为直接绑定因为它不是临时绑定的。


注意。所有标准参考均来自 C++14 (N3936)。由于 DR1288,本节从 C++11 进行了更改。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么我们不能用右值 volatile int&& 初始化对 const int 的引用? 的相关文章

  • 将数组向左或向右旋转一定数量的位置,复杂度为 o(n)

    我想编写一个程序 根据用户的输入 正 gt 负 include
  • UML类图:抽象方法和属性是这样写的吗?

    当我第一次为一个小型 C 项目创建 uml 类图时 我在属性方面遇到了一些麻烦 最后我只是将属性添加为变量 lt
  • 如何避免情绪低落?

    我有一个实现状态模式每个状态处理从事件队列获取的事件 根据State因此类有一个纯虚方法void handleEvent const Event 事件继承基础Event类 但每个事件都包含其可以是不同类型的数据 例如 int string
  • 如何忽略“有符号和无符号整数表达式之间的比较”?

    谁能告诉我必须使用哪个标志才能使 gcc 忽略 有符号和无符号整数表达式之间的比较 警告消息 gcc Wno sign compare 但你确实应该修复它警告你的比较
  • WPF 中的调度程序和异步等待

    我正在尝试学习 WPF C 中的异步编程 但我陷入了异步编程和使用调度程序的困境 它们是不同的还是在相同的场景中使用 我愿意简短地回答这个问题 以免含糊不清 因为我知道我混淆了 WPF 中的概念和函数 但还不足以在功能上正确使用它 我在这里
  • 在 Visual Studio 2008 上设置预调试事件

    我想在 Visual Studio 中开始调试程序之前运行一个任务 我每次调试程序时都需要运行此任务 因此构建后事件还不够好 我查看了设置的 调试 选项卡 但没有这样的选项 有什么办法可以做到这一点吗 你唯一可以尝试的 IMO 就是尝试Co
  • Cython 和类的构造函数

    我对 Cython 使用默认构造函数有疑问 我的 C 类 Node 如下 Node h class Node public Node std cerr lt lt calling no arg constructor lt lt std e
  • Web API - 访问 DbContext 类中的 HttpContext

    在我的 C Web API 应用程序中 我添加了CreatedDate and CreatedBy所有表中的列 现在 每当在任何表中添加新记录时 我想填充这些列 为此目的我已经覆盖SaveChanges and SaveChangesAsy
  • vector 超出范围后不清除内存

    我遇到了以下问题 我不确定我是否错了或者它是一个非常奇怪的错误 我填充了一个巨大的字符串数组 并希望在某个点将其清除 这是一个最小的例子 include
  • 如何衡量两个字符串之间的相似度? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 给定两个字符串text1 and text2 public SOMEUSABLERETURNTYPE Compare string t
  • Qt表格小部件,删除行的按钮

    我有一个 QTableWidget 对于所有行 我将一列的 setCellWidget 设置为按钮 我想将此按钮连接到删除该行的函数 我尝试了这段代码 它不起作用 因为如果我只是单击按钮 我不会将当前行设置为按钮的行 ui gt table
  • clang 实例化后静态成员初始化

    这样的代码可以用 GCC 编译 但 clang 3 5 失败 include
  • 当操作繁忙时,表单不执行任何操作(冻结)

    我有一个使用 C 的 WinForms 应用程序 我尝试从文件中读取一些数据并将其插入数据表中 当此操作很忙时 我的表单冻结并且无法移动它 有谁知道我该如何解决这个问题 这可能是因为您在 UI 线程上执行了操作 将文件和数据库操作移至另一个
  • C++ 复制初始化和直接初始化,奇怪的情况

    在继续阅读本文之前 请阅读在 C 中 复制初始化和直接初始化之间有区别吗 https stackoverflow com questions 1051379 is there a difference in c between copy i
  • 如何使我的表单标题栏遵循 Windows 深色主题?

    我已经下载了Windows 10更新包括黑暗主题 文件资源管理器等都是深色主题 但是当我创建自己的 C 表单应用程序时 标题栏是亮白色的 如何使我自己的桌面应用程序遵循我在 Windows 中设置的深色主题 你需要调用DwmSetWindo
  • 需要哪个版本的 Visual C++ 运行时库?

    microsoft 的最新 vcredist 2010 版 是否包含以前的版本 2008 SP1 和 2005 SP1 还是我需要安装全部 3 个版本 谢谢 你需要所有这些
  • C - 直接从键盘缓冲区读取

    这是C语言中的一个问题 如何直接读取键盘缓冲区中的数据 我想直接访问数据并将其存储在变量中 变量应该是什么数据类型 我需要它用于我们研究所目前正在开发的操作系统 它被称为 ICS OS 我不太清楚具体细节 它在 x86 32 位机器上运行
  • 为什么 C# Math.Ceiling 向下舍入?

    我今天过得很艰难 但有些事情不太对劲 在我的 C 代码中 我有这样的内容 Math Ceiling decimal this TotalRecordCount this PageSize Where int TotalRecordCount
  • 为什么我收到“找不到编译动态表达式所需的一种或多种类型。”?

    我有一个已更新的项目 NET 3 5 MVC v2 到 NET 4 0 MVC v3 当我尝试使用或设置时编译出现错误 ViewBag Title财产 找不到编译动态表达式所需的一种或多种类型 您是否缺少对 Microsoft CSharp
  • 防止索引超出范围错误

    我想编写对某些条件的检查 而不必使用 try catch 并且我想避免出现 Index Out of Range 错误的可能性 if array Element 0 Object Length gt 0 array Element 1 Ob

随机推荐