按值返回副本而不是移动

2024-02-17

为什么这个程序调用复制构造函数而不是移动构造函数?

class Qwe {
public:
    int x=0;
    Qwe(int x) : x(x){}
    Qwe(const Qwe& q) {
        cout<<"copy ctor\n";
    }
    Qwe(Qwe&& q) {
        cout<<"move ctor\n";
    }    
};

Qwe foo(int x) {
    Qwe q=42;
    Qwe e=32;
    cout<<"return!!!\n";
    return q.x > x ? q : e;
}

int main(void)
{
    Qwe r = foo(50);
}

结果是:

return!!!
copy ctor

return q.x > x ? q : e;用于禁用 nrvo。当我把它包起来时std::move,确实是感动了。但在《A Tour of C++》中,作者说 move c'tor 必须在可用时调用。

我做错了什么?


您没有以允许发生复制/移动省略的方式编写函数。副本替换为移动的要求如下:

[类.复制.省略]/3 https://timsong-cpp.github.io/cppwp/n4659/class.copy.elision#3:

在下面的复制初始化上下文中,移动操作可能 用来代替复制操作:

  • 如果 return 语句中的表达式是 a (可能带括号)id-表达式使用自动命名对象 正文中声明的存储期限或参数声明子句最里面的封闭函数或lambda 表达式

首先是选择副本构造函数的重载决策 执行起来就像对象是由右值指定的一样。如果第一个 重载决策失败或未执行,或者如果 所选构造函数的第一个参数不是右值引用 对于对象的类型(可能是 cv 限定的),重载决策是 再次执行,将该对象视为左值。

以上来自C++17,但C++11的措辞几乎相同。条件运算符is not一个在函数范围内命名对象的 id 表达式。

id 表达式会是这样的q or e在你的具体情况下。你需要name该范围内的对象。条件表达式不符合命名对象的条件,因此它必须执行副本。


如果您想在困难的文本墙上锻炼您的英语理解能力,那么这就是 C++11 的编写方式。需要一些努力才能看到​​ IMO,但它与上面的澄清版本相同:

当满足某些标准时,允许实施省略 类对象的复制/移动构造,即使复制/移动 对象的构造函数和/或析构函数有副作用。 [...] 这种复制/移动操作的省略称为复制省略,是 在以下情况下允许(可以组合起来) 消除多个副本):

  • 在具有类返回类型的函数的 return 语句中,当表达式是非易失性自动对象的名称(其他 比函数或 catch 子句参数)具有相同的 cv-非限定类型作为函数返回类型,复制/移动 直接构造自动对象可以省略操作 进入函数的返回值

当满足或将满足复制操作省略的标准时 满足保存源对象是函数参数的事实, 并且要复制的对象由左值、重载指定 首先执行选择副本构造函数的决议 就好像该对象是由右值指定的一样。如果过载解析 失败,或者如果所选的第一个参数的类型 构造函数不是对象类型的右值引用(可能 cv 限定),再次执行重载决策,考虑到 对象作为左值。

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

按值返回副本而不是移动 的相关文章

  • 使用 mono/nunit-console/4 在 Mac OS X 控制台上运行测试

    我安装了 Max OS X 10 11 1 上面装有 Xamarin 我编写了简单的测试类 只是为了测试在 Mac OS X 和 Ubuntu 上运行 Nunit 测试 该类实际上有一个返回字符串的方法 using System names
  • 有没有快速创建集合的方法?

    目前我正在创建一个像这样的新集 std set a s s insert a1 s insert a2 s insert a3 s insert a10 有没有办法创建s在一行 int myints 10 20 30 40 50 std s
  • 何时使用 =default 使析构函数默认?

    尽管对构造函数使用 default 对我来说很清楚 即强制编译器在其他构造函数存在时创建默认构造函数 但我仍然无法理解这两种类型的析构函数之间的区别 那些使用 default 的 那些没有显式定义并由编译器自动生成的 我唯一想到的是 gro
  • 类特定的新删除运算符是否必须声明为静态

    标准中是否要求类特定的 new new delete 和 delete 是静态的 我可以让它们成为非静态成员运算符吗 为什么需要它们是静态的 它们被隐式声明为静态 即使您没有键入 static
  • 指向特征矩阵的指针数组

    我在代码中使用 Eigen 的 MatrixXd 矩阵 在某个时刻我需要一个 3D 矩阵 由于 Eigen 没有三维矩阵类型 因为它仅针对线性代数进行了优化 因此我创建了一个 MatrixXd 类型的指针数组 Eigen MatrixXd
  • 找不到 assimp-vc140-mt.dll ASSIMP

    我已经从以下位置下载了 Assimp 项目http assimp sourceforge net main downloads html http assimp sourceforge net main downloads html Ass
  • 如何从文本文件读取整数到数组

    这就是我想做的 我对此有些不满 但我希望你能容忍我 这对我来说是一个非常新的概念 1 在我的程序中 我希望创建一个包含 50 个整数的数组来保存来自文件的数据 我的程序必须获取用户的文档文件夹的路径 2 文件的名称为 grades txt
  • 如何在服务器端按钮点击时关闭当前标签页?

    我尝试在确认后关闭当前选项卡 因此我将以下代码放在确认按钮的末尾 但选项卡没有关闭 string jScript ClientScript RegisterClientScriptBlock this GetType keyClientBl
  • 是否有相当于 Clang/LLVM 的 .spec 文件,在哪里可以找到参考?

    The gcc驱动程序可以配置为使用特定的链接器 特定的选项和其他细节 例如覆盖系统头 specs files 当前 截至撰写本文时 GCC 版本 4 9 0 的手册此处描述了规范文件 https gcc gnu org onlinedoc
  • ASP.NET MailMessage.BodyEncoding 和 MailMessage.SubjectEncoding 默认值

    很简单的问题 但我在 MSDN 上找不到答案 查找 ASP NET 将用于的默认值 MailMessage BodyEncoding and MailMessage SubjectEncoding 如果你不在代码中设置它们 Thanks F
  • 在 EnvDTE 中调试时捕获 VS 局部变量

    是否可以使用 EnvDTE 进行 vsix Visual Studio 扩展来捕获本地和调试窗口使用的调试数据 或者可以通过其他方法吗 我想创建一个自定义的本地窗口 我们可以修改它以根据需要显示一些较重的内容 而无需为高级用户牺牲原始的本地
  • .NET Core 中的跨平台文件名处理

    如何处理文件名System IO以跨平台方式运行类以使其在 Windows 和 Linux 上运行 例如 我编写的代码在 Windows 上完美运行 但它不会在 Ubuntu Linux 上创建文件 var tempFilename Dat
  • 了解使用 Windows 本机 WPF 客户端进行 ADFS 登录

    我已经阅读了大量有关 ADFS 与 NodeJS Angular 或其他前端 Web 框架集成以及一般流程如何工作的文献 并通过 Auth0 Angular 起始代码构建了概念证明 但我不明白如何这可以与本机 WPF Windows 应用程
  • 更改 Windows Phone 系统托盘颜色

    有没有办法将 Windows Phone 上的系统托盘颜色从黑色更改为白色 我的应用程序有白色背景 所以我希望系统托盘也是白色的 您可以在页面 XAML 中执行此操作
  • 如何在 DropDownList 中保留空格 - ASP.net MVC Razor 视图

    我在视图中通过以下方式绑定我的模型 问题是我的项目文本是格式化文本 单词之间有空格 如下所示 123 First 234 00 123 AnotherItem 234 00 123 Second 234 00 我想保留此项目文本中的空格 即
  • QFileDialog::getSaveFileName 和默认的 selectedFilter

    我有 getSaveFileName 和一些过滤器 我希望当用户打开 保存 对话框时选择其中之一 Qt 文档说明如下 可以通过将 selectedFilter 设置为所需的值来选择默认过滤器 我尝试以下变体 QString selFilte
  • 使我的 COM 程序集调用异步

    我刚刚 赢得 了在当前工作中维护用 C 编码的遗留库的特权 这个dll 公开使用 Uniface 构建的大型遗留系统的方法 除了调用 COM 对象之外别无选择 充当此遗留系统与另一个系统的 API 之间的链接 在某些情况下 使用 WinFo
  • 使用 QtWebEngine 将 C++ 对象暴露给 Qt 中的 Javascript

    使用 QtWebkit 可以通过以下方式将 C 对象公开给 JavascriptQWebFrame addToJavaScriptWindowObject如中所述https stackoverflow com a 20685002 5959
  • ASP.NET Core MVC 视图组件搜索路径

    在此处的文档中 https learn microsoft com en us aspnet core mvc views view components view aspnetcore 2 2 https learn microsoft
  • Java 和/C++ 在多线程方面的差异

    我读过一些提示 多线程实现很大程度上取决于您正在使用的目标操作系统 操作系统最终提供了多线程能力 比如Linux有POSIX标准实现 而windows32有另一种方式 但我想知道编程语言水平的主要不同 C似乎为同步提供了更多选择 例如互斥锁

随机推荐

  • Flutter守护进程启动失败

    我每次打开时都会收到此警告VS code 有什么办法可以解决这个问题吗 谢谢 我添加了这个警告的日志 我努力了扑干净 and 扑医生一切都很好 但是每次我打开 VS Code 时仍然出现此警告 我还遇到了一个问题 VS Code 显示没有设
  • 实体框架 Linq 等于值或为 null

    我正在尝试使用 linq 从视图中获取项目列表 其中字段 LocationId 为值或为 null LocationId 字段是 int 我正在尝试的代码是这样的 var items context Items Where d gt d L
  • 每个工人的最大日期

    考虑两个表 工作表有如下字段W ID W Name 课程表有如下字段C ID C Name C Date 一个工人可以选修多门课程 一门课程也可以由许多工人选修 因此 两个表之间存在多对多关系 打破多对多 并创建一个名为 Takes 的新表
  • 如何调整 IntelliJ 中行尾的位置

    在 IntelliJ 中 就像在 Eclipse 中一样 代码编辑器中有一条细灰色垂直线 我假设就像在 Eclipse 中一样 该行显示了 行尾 应该在的位置 2个问题 1 在IntelliJ中哪里可以调整一行的长度 2 如果不使用与 1
  • React-Router:使用 Navlink 将道具从一个组件传递到另一个组件

    我在用
  • 如何通过svelte访问本地json文件?

    现在我使用 onMount 异步函数来访问 const dataAPI jsfwperf json let data onMount async gt const res await fetch dataAPI then res gt re
  • 在浏览器中使用模块(没有 WebPack)

    我正在摸索 ES6 的过程 遇到了模块 很好 在学习过程中 我试图看看是否可以在浏览器中使用它们withoutWebPack 我还没学过 所以 我的 JS 目录中有以下文件 文件夹结构 js lib for complied es6 via
  • 如何在单个android应用程序中正确导入多个unity模块,避免android studio中不同unity模块之间的名称冲突?

    我已经导入了两个统一模块 三角形模块和立方体模块 public class MainActivity extends AppCompatActivity Override protected void onCreate Bundle sav
  • 通过 crypto-js 的 base64 编码器

    我想将数字编码为字符 如何在输出中编码为 Base64 Code const CryptoJS require crypto js function msg return 7543275 I want to encrypt this num
  • Docker Compose 和 Kubernetes 有什么区别?

    这个问题的答案是社区努力 help privileges edit community wiki 编辑现有答案以改进这篇文章 目前不接受新的答案或互动 在深入研究 Docker Google Cloud 和 Kubernetes 时 如果还
  • logd 快捷方式在 Intellij 和 Kotlin 中不起作用

    使用 logt logd loge 等快捷方式在 Intellij 中记录 Java 非常简单 但我搬到了 Kotlin 我注意到这些快捷方式不再起作用了 我不知道这是否与我的配置有关 如果不是 我该如何解决这个问题 您应该创建单独的模板以
  • 让应用程序布局与 Bootstrap 4 页面配合使用

    我使用的是 Domino 9 0 1 并成功安装了 Bootstrap Library 1 0 0 201403171254 在应用程序配置 Xsp 属性 常规下 我将主题设置为 bootstrapv3 1 1 并在应用程序配置 Xsp 属
  • 页面刷新后保留值

    我在 C 中使用按钮控件 验证按钮 我在我的项目中定义了一些全局变量 当我单击该按钮时 会发生一些表单验证 并且另一个按钮 保存按钮 可见 问题是当我单击验证按钮时 当前页面刷新并且全局变量不包含值 它显示为空 即使在页面刷新后 我如何维护
  • 序列化性能和 Google Android

    我正在寻找加快序列化性能的建议 特别是在使用 Google Android 时 对于我正在从事的一个项目 我试图将数百个对象从服务器中继到 Android 应用程序 并经历各个阶段以获得我需要的性能 首先 我尝试了一个糟糕的 XML 解析器
  • 用于注册和忘记密码的不同电子邮件验证消息

    使用 AWS 的 Cognito 可以获得很多好处 因为大多数功能 如果不是全部 已经由 AWS 实现 但我遇到了一种情况 我不确定如何使用 Cognito 来实现 考虑以下两种情况 Sign up 用户通过提供电子邮件和密码进行注册 将向
  • 哪些字符可以作为使用 Esprima 的 JavaScript 中的运算符?

    From 以前的 https stackoverflow com q 20762338 1420197问题 我学会了如何扩展 JavaScript 语言以支持更多运算符 由我创建 There Benjamin 使用 Esprima 并创建了
  • 我应该使用 std::begin 与数组吗?

    作为一个简单的例子 看一下这段代码 或者想象一下特定于数组的代码而不是模板和其他通用编码技术 int a 1 2 3 7 8 9 55 vector
  • 如何使用 $location 服务对 angularjs 控制器进行单元测试

    我正在尝试创建一个简单的单元测试来测试我的显示功能 我收到以下错误 TypeError Object has no method show 这好像是 rootScope不是控制器的范围吗 这是我的控制器 function Opponents
  • 减慢线程速度的最佳方法?使用 Sleep() 可以吗?

    我编写了一个 C 库 它执行一些非常繁重的 CPU 工作 所有数学和计算 如果留给它自己的设备 将很容易消耗 100 的所有可用 CPU 资源 它也是多线程的 以达到可用逻辑的数量 机器上的核心 因此 我在使用该库的软件应该调用的主计算循环
  • 按值返回副本而不是移动

    为什么这个程序调用复制构造函数而不是移动构造函数 class Qwe public int x 0 Qwe int x x x Qwe const Qwe q cout lt lt copy ctor n Qwe Qwe q cout lt