C++0x 右值引用和临时值

2024-04-07

(我在 comp.std.c++ 上问了这个问题的变体,但没有得到答案。)

为什么调用f(arg)在此代码中调用 const ref 重载f?

void f(const std::string &); //less efficient
void f(std::string &&); //more efficient

void g(const char * arg)
{
     f(arg);
}

我的直觉告诉我f(string &&)应选择过载,因为arg无论如何都需要转换为临时值,并且临时值与右值引用的匹配比左值引用更好。

这不是 GCC 和 MSVC 中发生的情况(编辑:感谢 Sumant:这在 GCC 4.3-4.5 中不会发生)。至少在 G++ 和 MSVC 中,任何左值都不会绑定到右值引用参数,even if创建了一个中间临时文件。事实上,如果 const ref 重载不存在,编译器会诊断错误。然而,写作f(arg + 0) or f(std::string(arg)) does按照您的预期选择右值引用重载。

从我对 C++0x 标准的阅读来看,在考虑以下情况时,似乎应该考虑将 const char * 隐式转换为字符串:f(string &&)是可行的,就像传递 const 左值引用参数时一样。第 13.3 节(重载解析)在很多地方都没有区分右值引用和常量引用。另外,如果存在中间临时值,则似乎阻止左值绑定到右值引用(13.3.3.1.4/3)的规则不应该适用 - 毕竟,从临时值移动是完全安全的。

Is this:

  1. 我误读/误解了标准,其中实现的行为是预期的行为,并且有一些充分的理由为什么我的示例应该按照它的方式运行?
  2. 编译器供应商不知何故都犯了一个错误?还是基于常见实施策略的错误?或者例如错误GCC(首先实现左值/右值引用绑定规则的地方),被其他供应商复制了?
  3. 标准中的缺陷,或者意外的后果,或者应该澄清的事情?

编辑:我有一个相关的后续问题:C++0x 右值引用 - 左值-右值绑定 https://stackoverflow.com/questions/2749263/c0x-rvalue-references-lvalues-rvalue-binding


根据 FCD 的说法,GCC 的做法是错误的。 FCD 表示8.5.3关于引用绑定

  • 如果引用是左值引用并且初始化表达式是 [左值/类类型] ...
  • 否则,该引用应为对非易失性 const 类型的左值引用(即 cv1 应为 const),或者该引用应为右值引用,并且初始值设定项表达式应为右值或具有函数类型。

您致电的情况std::string &&它们都不匹配,因为初始化器是一个lvalue。它没有到达创建临时右值的位置,因为该顶级项目符号已经需要一个右值。

现在,重载解析不直接使用引用绑定来查看是否存在隐式转换序列。相反,它说在13.3.3.1.4/2

当引用类型的参数未直接绑定到参数表达式时,转换序列是根据 13.3.3.1 将参数表达式转换为引用的基础类型所需的序列。

因此,重载决策会找出一个获胜者,即使该获胜者实际上可能无法绑定到该参数。例如:

struct B { B(int) { /* ... */ } };
struct A { int bits: 1; };

void f(int&);
void f(B);
int main() { A a; f(a.bits); }

参考绑定位于8.5禁止位域绑定到左值引用。但重载解析表明转换序列是转换为的序列int,因此即使稍后进行调用时,调用格式不正确,也会成功。因此我的位域示例格式不正确。如果要选择的话B版本,它会成功,但需要用户定义的转换。

However,该规则存在两个例外。这些都是

除了隐式对象参数(参见 13.3.1)外,如果需要将非 const 的左值引用绑定到右值或将右值引用绑定到左值,则无法形成标准转换序列。

因此,以下调用是有效的:

struct B { B(int) { /* ... */ } };
struct A { int bits: 1; };

void f(int&); /* binding an lvalue ref to non-const to rvalue! */
void f(B);
int main() { A a; f(1); }

因此,你的例子调用const T& version

void f(const std::string &);
void f(std::string &&); // would bind to lvalue!

void g(const char * arg) { f(arg); }

但是,如果你说f(arg + 0),您创建一个右值,因此第二个函数是可行的。

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

C++0x 右值引用和临时值 的相关文章

  • 通过增加索引之和来生成排序组合的有效方法

    对于启发式算法 我需要一个接一个地评估特定集合的组合 直到达到停止标准 由于它们很多 目前我正在使用以下内存高效迭代器块生成它们 受到 python 的启发 itertools combinations http docs python o
  • Subversion 和 Visual Studio 项目的最佳实践

    我最近开始在 Visual Studio 中处理各种 C 项目 作为大型系统计划的一部分 该系统将用于替换我们当前的系统 该系统是由用 C 和 Perl 编写的各种程序和脚本拼凑而成的 我现在正在进行的项目已经达到了颠覆的临界点 我想知道什
  • System.IO.IOException:由于意外>数据包格式,握手失败?

    有谁知道这意味着什么 System Net WebException 底层连接已关闭 发送时发生意外错误 gt System IO IOException 由于意外 握手失败 数据包格式 在 System Net Security SslS
  • 在 C# 中生成 HMAC-SHA1

    我正在尝试使用 C 来使用 REST API API 创建者提供了以下用于 hmac 创建的伪代码 var key1 sha1 body var key2 key1 SECRET KEY var key3 sha1 key2 var sig
  • (const T v) 在 C 中从来都不是必需的,对吗?

    例如 void func const int i 在这里 const是不必要的 因为所有参数都是按值传递的 包括指针 真的吗 C 中的所有参数确实都是按值传递 这意味着无论您是否包含该参数 实际参数都不会改变const or not 然而
  • 将字符串中的“奇怪”字符转换为罗马字符

    我需要能够将用户输入仅转换为 a z 罗马字符 不区分大小写 所以 我感兴趣的角色只有26个 然而 用户可以输入他们想要的任何 形式 的字符 西班牙语 n 法语 e 和德语 u 都可以包含用户输入中的重音符号 这些重音符号会被程序删除 我已
  • 在 C# Winforms 应用程序中嵌入 Windows XP 主题

    我有一个旧版 C Windows 窗体应用程序 其布局是根据 Windows XP 默认主题设计的 由于需要将其作为 Citrix 应用程序进行分发 该应用程序现在看起来像经典主题应用程序 因为 Citrix 不鼓励使用主题系统服务 所以
  • 带 If 的嵌套 For 循环的时间复杂度

    void f int n for int i 1 i lt n i if i int sqrt n 0 for int k 0 k lt pow i 3 k do something 我的思考过程 执行if语句的次数 sum i 1 to
  • 为什么 clang 使用 -O0 生成低效的 asm(对于这个简单的浮点和)?

    我正在 llvm clang Apple LLVM 版本 8 0 0 clang 800 0 42 1 上反汇编此代码 int main float a 0 151234 float b 0 2 float c a b printf f c
  • libxml2 xmlChar * 到 std::wstring

    libxml2似乎将所有字符串存储在 UTF 8 中 如xmlChar xmlChar This is a basic byte in an UTF 8 encoded string It s unsigned allowing to pi
  • C++ 插件的“最适合”动态类型匹配

    我有一个几乎所有东西都是插件的架构 该架构以图形用户界面为基础 其中每个插件都由一个 表面 即用户可以通过其与插件交互的 UI 控件 表示 这些表面也是插件 每当添加新插件时 瘦主机都会自动确定哪个可用表面与其最匹配的 UI 如何在 C 中
  • 使用 WF 的多线程应用程序的错误处理模式?

    我正在写一个又长又详细的问题 但只是放弃了它 转而选择一个更简单的问题 但我在这里找不到答案 应用程序简要说明 我有一个 WPF 应用程序 它生成多个线程 每个线程执行自己的 WF 处理线程和 WF 中的错误 允许用户从 GUI 端进行交互
  • 分配器感知容器和propagate_on_container_swap

    The std allocator traits模板定义了一些常量 例如propagate on container copy move assign让其他容器知道它们是否应该在复制或移动操作期间复制第二个容器的分配器 我们还有propag
  • C# 中的常量和只读? [复制]

    这个问题在这里已经有答案了 可能的重复 const 和 readonly 之间有什么区别 https stackoverflow com questions 55984 what is the difference between cons
  • asp.net网格分页的SQL查询

    我在用iBatis and SQLServer 使用偏移量和限制进行分页查询的最佳方法是什么 也许我添加该列ROW NUMBER OVER ORDER BY Id AS RowNum 但这只会阻止简单查询的数据访问 在某些情况下 我使用选择
  • 0-1背包算法

    以下 0 1 背包问题是否可解 浮动 正值和 浮动 权重 可以是正数或负数 背包的 浮动 容量 gt 0 我平均有 这是一个相对简单的二进制程序 我建议用蛮力进行修剪 如果任何时候你超过了允许的重量 你不需要尝试其他物品的组合 你可以丢弃整
  • Visual Studio 2017 完全支持 C99 吗?

    Visual Studio 的最新版本改进了对 C99 的支持 最新版本VS2017现在支持所有C99吗 如果没有 C99 还缺少哪些功能 No https learn microsoft com en us cpp visual cpp
  • 为什么 Linux 对目录使用 getdents() 而不是 read()?

    我浏览 K R C 时注意到 为了读取目录中的条目 他们使用了 while read dp gt fd char dirbuf sizeof dirbuf sizeof dirbuf code Where dirbuf是系统特定的目录结构
  • C语言声明数组没有初始大小

    编写一个程序来操纵温度详细信息 如下所示 输入要计算的天数 主功能 输入摄氏度温度 输入功能 将温度从摄氏度转换为华氏度 独立功能 查找华氏度的平均温度 我怎样才能在没有数组初始大小的情况下制作这个程序 include
  • 在 Xamarin 中获取 OutOfMemoryException

    java lang OutOfMemoryError 考虑增加 JavaMaximumHeapSize Java 执行时内存不足 java exe 我的 Visualstudio Xamarin 项目出现内存不足异常 请帮助我如何解决此问题

随机推荐

  • Spring Cloud 配置服务器不刷新

    我正在设置一个 Spring 云服务器来读取内部 Stash 目录 服务器第一次加载 但如果我更新 git 中的属性 它们不会得到反映 直到我重新启动云服务器 我尝试 POST 到 refresh 端点 我使用的是 Windows 我看到一
  • 使用JMS临时队列进行同步使用是一个好习惯吗?

    如果我们使用 临时队列 的 JMS 请求 回复机制 该代码是否可扩展 截至目前 我们不知道是否会支持每秒 100 个请求 或者每秒 1000 个请求 下面的代码是我正在考虑实现的代码 它以 同步 方式使用 JMS 关键部分是创建 消费者 以
  • @Cachable注解不起作用

    我们在项目中使用 ehcache 进行缓存 import com googlecode ehcache annotations Cacheable Other imports Component public class Authentic
  • 使用 laravel 将 .JSON 文件保存到数据库

    总的来说 我对 Laravel 和 PHP 非常陌生 我所做的大部分工作都与在线教程相关 我知道如何将用户名或密码等单个项目保存到数据库中 但在存储整个文件时我一无所知 这就是我的数据库当前在迁移文件中的格式 public function
  • 合并两个 PDF

    import PyPDF2 import glob import os from fpdf import FPDF import shutil class MyPDF FPDF adding a footer containing the
  • 如何使用 PHP 在 S3 存储桶中创建文件夹

    我正在尝试在 S3 亚马逊存储桶中创建一个文件夹 但我发现很难找到正确的文档来充分解释所需内容 我有以下用于创建文件夹的代码 伪代码 任何人都可以解释或提供我需要在代码中放置的参数示例 use vendor aws S3 S3Client
  • 符号化 Swift Package Manager 构建

    Swift Package Manager可以是构建快速项目的便捷方法 并且 如果您 删除它添加到二进制文件中的绝对工具链 rpath https github com apple swift package manager blob 2d
  • cygwin_exception::open_stackdumpfile:将堆栈跟踪转储到 *.exe.stackdump

    我收到 cygwin exception open stackdumpfile 将堆栈跟踪转储到 TestProject exe stackdump 错误 我的项目只不过是一个 C HalloWorld 项目 其中包含一个附加类 我在其中设
  • Knockback.js 生产准备好了吗? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • UIButton 调整大小以适合其 titleLabel

    我有一个UIButton我将其添加到故事板中的视图控制器的视图中 我添加居中约束来定位它 并添加前导空间约束来限制其宽度 在代码中我添加 self button titleLabel numberOfLines 0 self button
  • 玩!框架+DynamoDB

    作为 Play 框架的新手 我想知道它是否比我想象的更容易 但是是否可以将 DynamoDB 与 Play 框架一起使用 由于 DynamoDB 是一个 NoSQL 数据库 我预计您需要使用特定的模块 而由于 Dynamo 最近才发布 因此
  • jQuery TABS 无法在新的 ASP .NET MVC4 项目下工作

    我所做的是 我已经创建了新的 ASP NET MVC4 项目 我用过http jqueryui com tabs http jqueryui com tabs 示例代码 所以我得到了这个 布局 cshtml Style
  • 在运行时获取本地对象/变量的列表

    我正在尝试创建一个简单的记录器来检查客户端发生的情况 如何获取本地列表 调试时在 Visual Studio 上显示 有点像当断点被击中时 对象 变量的当前现有实例显示在 本地 选项卡上 或者我应该在写入日志时获取变量的当前值吗 有趣的事情
  • 在 Windows 虚拟机中运行 Docker

    Using 适用于 Windows 10 的 Docker 桌面 MobaXterm 到 RDP 到 Windows 10 VM 硒 3 141 59 我目前正在尝试在 docker 容器中运行 selenium Grid 但遇到了一些问题
  • 如何在 jQuery 中设置文本框值?

    如何使用 jQuery 将某个值正确加载到文本框中 尝试了下面的 但我得到了 object Object 作为输出 请告诉我这一点 我是 jQuery 的新手 proc function x y var str1 pid value var
  • 使用整数作为模板参数时出现编译错误

    下面这段代码有什么问题 template
  • lxml 更改 Unicode 字符

    我正在使用 lxml 读取 xml 文件并更改一些详细信息 但是 运行时我发现即使我只是使用lxml读取文件然后再次写出来 如下所示 fil iTunes Music Library XML tre etree parse fil tre
  • Bootstrap 图标未显示在已发布的 ASP.NET MVC 应用程序中

    注意 请前往编辑 2 部分查看摘要 我有一个 ASP NET MVC 4 应用程序 我将 twitter Bootstrap 集成到其中 Bootstrap 工作正常 但当我发布应用程序时 图标无法正确显示 我尝试重新发布该应用程序 但没有
  • 在 XAML 中设置命令目标

    我很难理解 RoutedCommand 的 CommandTarget 属性 基本上 我有一些在用户控件 而不是窗口 中实现的静态命令 我在用户控件中创建命令绑定 如果我在用户控件中声明按钮 那么我就可以使用我的路由事件 但是 当按钮位于用
  • C++0x 右值引用和临时值

    我在 comp std c 上问了这个问题的变体 但没有得到答案 为什么调用f arg 在此代码中调用 const ref 重载f void f const std string less efficient void f std stri