return 语句是否为按值返回的函数创建临时对象?

2024-05-03

当我学习 C++11 右值引用和移动语义时,我开始对函数如何返回值来初始化变量感到困惑。看下面的例子:

Widget makeWidget()
{
    Widget w;
    …
    return w;
}
Widget w1 = makeWidget();

这里我假设没有 RVO(即编译不会消除复制/移动)。执行return语句时return w;,函数执行:

1)在众所周知的位置(调用者知道的某个固定寄存器或内存位置)初始化一个临时对象,其值成为函数的返回值?然后调用者获取这个对象进行复制初始化w1? Or

2)该函数获取调用者传递的内存位置w1和函数的自动变量w用于复制初始化w1? (这已经是某种 RVO 了吗?或者某种内联函数行为?或者它是一种可能的调用约定?)

如果是第一种情况,并且 return 创建一个临时对象,则将有两个复制构造函数调用,一个创建临时对象,一个创建w1。如果是第二种情况,则只会调用一次复制构造函数来创建w1.

现在假设我们有 RVO。那么如果return的行为是case1),那么编译器可以通过构造来消除临时的复制构造w直接在众所周知的位置获取返回值。如果 return 的行为类似于 case2),那么 RVO 在这种情况下甚至可以创建自动变量w直接位于分配的内存位置w1。我对RVO的理解正确吗?


现在让我添加移动语义。再次假设没有 RVO,请看以下示例:

Widget makeWidget()
{
    Widget w;
    …
    return std::move(w);
}
Widget w1 = makeWidget();

现在再次针对上面的两种情况:

1)我期望有两个动作吗:第一个动作来自初始化温度Widget带有表达式的对象std::move(w);第二步来自初始化w1随着温度Widget哪个是右值?或者

2)只有一招:初始化w1与表达std::move(w) ?


最后一个问题:返回行为是否取决于它返回的是 POD 类型还是类类型?


1)复制初始化一个临时对象,其值变为 函数的返回值,位于众所周知的位置(某些固定寄存器 或调用者知道的内存位置)?然后调用者获取这个对象 复制初始化w1?

大概是这样。通常,调用者会分配必要的堆栈空间来保存返回值,并将指针作为隐藏参数传递给它。

请注意,两次复制初始化实际上都是移动。

那么编译器可以通过以下方式省略临时的构造 建造w直接在众所周知的位置获取返回值。

是的(但这是一个举动)。并且它可以进一步省略构建w1通过传递其地址作为应构造返回值的位置。

Widget makeWidget()
{
    Widget w;
    …
    return std::move(w);
}
Widget w1 = makeWidget();

这是一个不可取消的举动(来自std::move(w)到临时返回值)和一个可消除的移动(从临时返回值到w1).

返回行为是否取决于它返回的是 POD 类型还是 班级类型?

它可以。根据平台 ABI,一些小的 POD 类型可能会在寄存器中返回。

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

return 语句是否为按值返回的函数创建临时对象? 的相关文章

随机推荐

  • 如何在PHP中使用curl GET发送原始数据?

    我正在开发 REST API 虽然很容易在 cURL 中为 POST 请求设置原始 JSON 数据 payload json encode array user gt data attach encoded JSON string to t
  • CKFinder 如何在选择图像(文件:选择)时获取尺寸 URL 和尺寸(宽度/高度)?

    我正在使用 CkFinder 3 成功上传图像后 我需要能够在用户单击 选择 按钮后进行检测 文件名 ID url 原始图像的宽度和高度 目前我正在使用files choose但我找不到有关 cb 事件的信息 知道如何解决吗 代码示例将不胜
  • TSConfig JSX:React JSX 与 React

    在将 Typescript 与 React 一起使用时 我们必须指定jsx in compilerOptions in tsconfig json file It has preserve react react native react
  • go:找到模块但不包含包

    我正在尝试安装 go 的网络包 但收到 不包含包错误 终端截图 我咨询过 go 模块 latest 已找到但不包含包 https stackoverflow com questions 62974985 go module latest f
  • 使用 Pandas 滚动差异

    您好 我正在尝试使用 Pandas 滚动函数来计算下表中的滚动差异 我正在尝试生成 每月可用项目 列中的值 但没有得到任何结果 请帮忙 Item Adds Subtracts Month Monthly Available items A
  • 在opencv中保存帧而不压缩

    我正在尝试使用写 OpenCV 函数 我想保存帧 TIFF扩大 我遇到的问题是保存的图像被压缩 所以我无法使用它们 知道如何摆脱这种压缩吗 提前致谢 不要介意西奇说的话 TIFF 标志通过 LZW 压缩硬编码在 opencv 二进制文件中
  • 如何分发仅二进制的 go 包

    我想以二进制形式分发包而不包含源代码 我的演示项目目录结构是这样的 demo greet greet go hi hi go hello hello go main go main go package main import fmt de
  • 在提交 Google 表单时找不到具有给定 ID 的项目

    我创建了一个在 Google 表单上运行 onSubmit 的脚本 它应该获取上传到表单的图像的 ID 获取 Blob 形式的图像 然后将其转发到某个电子邮件地址 问题是 有时 大约十分之一 脚本会给出以下错误 例外 找不到具有给定 ID
  • 获取 WSA 错误代码的格式化消息

    我在 win32 C 应用程序中使用winsock2 我将使用 MessageBox 显示可以通过调用 WSAGetLastError 检索的网络错误 我怎样才能做到这一点 我看到 FormatMessage 但我不明白如何使用它 例如 以
  • C# Socket.receive连续接收0字节且循环中不阻塞

    我正在尝试用 C 编写一个最简单的多线程 TCP 服务器 它接收来自多个客户端的数据 每次连接新客户端时 都会建立套接字连接 并将套接字作为参数传递给新类函数 之后运行 while 循环并接收数据 直到客户端连接为止 这里的问题是 sock
  • 为多线程 UDP 客户端执行“close ()”时套接字描述符未释放

    我在下面编写了 UDP 客户端 它基本上生成一个单独的线程来接收数据报 但是数据报仅在主线程中发送 现在 在 Linux 发行版上实例化 udpClient 1 UDP 客户端后按 ctrl D 实现退出循环 围绕 getline 调用 并
  • 创建数据库连接的成本很高吗?

    为什么创建数据库连接的成本很高 比如它到底消耗了什么有限资源 带宽 网络往返 CPU 通常创建成本高昂意味着它会消耗一些资源 例如 cpu 磁盘 io 但在连接的情况下我只能想到同步 确认等所需的时间 您没有说明您要问的数据库是什么 所以这
  • Microsoft Graph API 授权错误:无效受众

    我知道这是一个很长的问题 但如果有人能与我分享他们的想法或经验 我真的很感激 因为我已经解决这个问题几天了 现在正在尝试很多事情 我有一个 ASP Net Core 3 1 Web API 应用程序和一个 ASP NET Core 3 1
  • 对整数进行反直觉测试:63 = (45 x 1.4) = 62

    我写了一个 可能不是特别好 函数来测试一个数字是否是整数 is wholeNumber lt function x x floor x 一般来说 这个函数对我的目的来说效果很好 因为我实际上只考虑用少数小数位测试数字的情况 所以我天真的理解
  • Bixby - 将用户输入从一次操作传递到其他操作

    我正在尝试实现从一个操作读取用户输入并在其他屏幕中读取 例如 user xx Bixby who s there user yyy Bixby yyy who I am able to read user input yyy but una
  • 使用python同时播放两个正弦音

    我正在使用 python 来播放正弦音 音调基于计算机的内部时间 以分钟为单位 但我想根据秒同时播放一个音调 以获得和谐或双重的声音 这就是我到目前为止所拥有的 有人能指出我正确的方向吗 from struct import pack fr
  • 如何在alert()之后给予focus()?

    我有类似的东西
  • 通过 Git/SVN 将前缀 ? 添加到代码中

    怎么加前缀 v VersionNumber使用 Git SVN 高效地访问存储库中的每个文件 我发现 SO 使用这种做法为其存储库中的每个特定文件提供版本号 他们使用SVN 我想知道如何使用 Git 做同样的事情 举几个例子 1 2 在你的
  • 为什么实体框架需要 ICollection 来延迟加载?

    我想编写一个丰富的域类 例如 public class Product public IEnumerable
  • return 语句是否为按值返回的函数创建临时对象?

    当我学习 C 11 右值引用和移动语义时 我开始对函数如何返回值来初始化变量感到困惑 看下面的例子 Widget makeWidget Widget w return w Widget w1 makeWidget 这里我假设没有 RVO 即