为什么我们先复制然后移动?

2023-12-08

我在某处看到代码,其中有人决定复制一个对象,然后将其移动到类的数据成员。这让我感到困惑,因为我认为移动的全部目的是为了避免复制。这是示例:

struct S
{
    S(std::string str) : data(std::move(str))
    {}
};

这是我的问题:

  • 为什么我们不采用右值引用str?
  • 副本不会很贵,尤其是考虑到类似的东西std::string?
  • 作者决定复制然后搬家的原因是什么?
  • 我什么时候应该自己做这件事?

在我回答你的问题之前,你似乎弄错了一件事:在 C++11 中按值获取并不总是意味着复制。如果传递右值,则为moved(假设存在可行的移动构造函数)而不是被复制。和std::string确实有一个移动构造函数。

与 C++03 不同,在 C++11 中,按值获取参数通常是惯用的做法,原因我将在下面解释。另请参阅StackOverflow 上的问答有关如何接受参数的更通用的指南。

为什么我们不采用右值引用str?

因为这将导致无法传递左值,例如:

std::string s = "Hello";
S obj(s); // s is an lvalue, this won't compile!

If S只有一个接受右值的构造函数,上面的代码无法编译。

副本不会很贵,尤其是考虑到类似的东西std::string?

如果你传递一个右值,那就是moved into str,最终将被移入data。不会执行任何复制操作。另一方面,如果您传递左值,则该左值将是copied into str,然后搬进data.

总而言之,右值有两次移动,左值有一次复制和一次移动。

作者决定复制然后搬家的原因是什么?

首先,正如我上面提到的,第一个并不总是副本;这就是说,答案是:“因为它是有效的(移动std::string物品便宜)且简单".

假设移动成本较低(此处忽略 SSO),则在考虑此设计的整体效率时实际上可以忽略它们。如果我们这样做,我们就会有一份左值副本(如果我们接受对左值的引用,我们就会拥有一份左值副本)const)并且没有右值的副本(如果我们接受对左值的引用,我们仍然会有一个副本const).

这意味着按值获取与按左值引用获取一样好const当提供左值时,并且当提供右值时更好。

P.S.:为了提供一些背景,我相信这是问答OP指的是。

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

为什么我们先复制然后移动? 的相关文章

随机推荐

  • 有人可以澄清 Android 上下文引用吗?

    我的误会还在继续 任何人都可以引用正确使用的参考资料get Context 我得到了关于使用的相互矛盾的建议getBaseContext getApplicationContext and getContext 我的理解是使用this是一个
  • 如何在VIPS中进行透视扭曲变换?

    是否可以执行以下 ImageMagick透视扭曲使用 VIPS 命令 如果是这样 命令是什么 使用ruby vips convert my file png matte virtual pixel transparent distort P
  • 为小字符增大 SKLabelNode 的触摸区域

    我在我的游戏中添加了一个老式的高分输入屏幕 用户点击每个字母来输入他们的名字 每个字母 符号或短语 DEL SP 等 都是一个SKLabelNode而且点击 和 非常困难 不过字符和一些符号 每次点击都会通过通常的方式检测到touchesB
  • 在 x86-64、skylake 上以可重启序列优化 percpu 2 级位向量

    我很好奇如何最好地优化下面的程序集 特别是 跳到此处查看程序集 下的代码块中的部分 以便于 control f 搜索 我正在编写一些代码 HOT HOT HOT 路径基本上是在位向量中查找 0 位并返回该位 位向量由以下部分组成 struc
  • 如何使用 jQuery 查找文本并替换

    我试图找到一个解决方案来搜索 DOM 中包含的文本字符串 Tony 并将其替换为文本字符串 Tiger 有人对如何做到这一点有任何见解或想法吗 我猜它需要每个语句加上替换函数并且可能包含 谢谢 杰克 您可以使用它来搜索 body 元素的所有
  • Symfony2:AJAX请求:如何在需要时处理身份验证?

    使用 Symfony2 我实现了 AJAX 操作来管理应用程序中的一些书签 添加 删除 因此 用户需要经过身份验证才能继续 我有一个将用户重定向到登录页面的解决方案 但我认为最好使用事件来处理此重定向 实际解决方案 检查用户身份验证的方式与
  • 将条件应用于 MongoDB 中同一字段的多个文档

    我有一个具有以下结构的文档 user id 123 tag tag1 user id 123 tag tag2 user id 123 tag tag3 user id 456 tag tag1 给定用户 ID 我想查找该用户是否拥有包含所
  • 如何在 phing 中迭代(循环)目录?

    我想为一些插件创建 phing 任务 所以目录结构类似于 root plugin1 index php plugin2 index php etc 我想在每个子目录上运行相同的任务 例如 为plugin1生成文档 为plugin1运行单元测
  • Python MySQLdb 字符串替换不添加引号

    我想对逗号分隔的列表使用字符串替换 例如 query SELECT id name image id FROM users WHERE id IN s values join uids results dbc getAll query va
  • Java中的邻接矩阵

    我对图表和邻接矩阵感到非常困惑 我正在为一个类做作业 其中我有一个节点的文本文件和一个边的文本文件 我必须读取它们中的每一个并将它们制作为一个图表 然后我可以在其中执行操作 例如确定图表是否是连接 寻找最小生成树 遍历并寻找路径 不过 我以
  • 带有嵌入字体的 @font-face 不起作用

    我有网站 http kuvaklubi fi我尝试使用字体的地方 Century Gothic 我的电脑上不存在此字体 Installed fonts 我想通过以下方式将此字体嵌入到 css 中 font face 我已经生成了一些字体文件
  • django.db.backends.dummy 和 django.db.backends.mysql 有什么区别?

    django db backends dummy 和 django db backends mysql 有什么区别 我发现有人使用dummy和mysql 但我搜索后不知道他们的区别 django db backends mysql后台数据库
  • 获取类层次结构的所有字段[重复]

    这个问题在这里已经有答案了 我有课 ClassA public String filedA ClassB extends ClassA public String filedB ClassC extends ClassB public St
  • 使用spatiallite 将 GIS 缓冲值度以米为单位

    我是 Spatialite 的新手 我有以下查询 select A from linka as A pointa as B where Contains Buffer B Geometry 100 A Geometry 我实际上想创建 10
  • 强制一种方法等待另一种方法完成

    在我的原始视图控制器中 在转到目标视图控制器之前 我调用一个获取关键参数的方法 然后在以下方法中在目标视图控制器中设置关键参数 然而 关键参数是在之前设置的doSomethingToGetKey方法已完成 因此传递了一个空值 我想知道是否有
  • 如何创建自己的资源名称?

    我可以在中使用我自己的资源名称吗themes xml 例如
  • 由于未注册 Windows.Launch 合同,Windows 10 分配的访问应用程序无法启动

    我有一个 WPF 应用程序 我已使用以下命令将其转换为 UWP 应用程序DesktopAppConverter为了运行它分配的访问权限模式 转换后的应用程序在非分配访问模式下运行时可以工作 可以安装并正常运行 但是 当我将其设置为分配的访问
  • 无法使用 cURL 将 SSH 密钥发送到 Github

    我正在尝试将我的公共 ssh 密钥发送到 Github 我将密钥设置为 shell 中的变量 但它给出了key is invalid You must supply a key in OpenSSH public key format错误
  • 在堆栈弹出中反应本机路由通量重新渲染组件

    如何重新运行 React 组件生命周期方法来确定在从堆栈转换回以前的屏幕时是否需要重新渲染React Native 路由器 Flux 设想 场景 A gt B gt A 假设 A 是初始场景 我们使用 a 从 A 导航到 B推即 Actio
  • 为什么我们先复制然后移动?

    我在某处看到代码 其中有人决定复制一个对象 然后将其移动到类的数据成员 这让我感到困惑 因为我认为移动的全部目的是为了避免复制 这是示例 struct S S std string str data std move str 这是我的问题