C++11 移动语义是在做一些新的事情,还是只是让语义更清晰?

2024-01-03

我基本上想弄清楚,整个“移动语义”概念是全新的,还是只是使现有代码更易于实现?我总是对减少调用复制/构造函数的次数感兴趣,但我通常使用引用(可能还有 const)来传递对象,并确保我始终使用初始化列表。考虑到这一点(并查看了整个丑陋的 && 语法),我想知道是否值得采用这些原则或像我已经做的那样简单地编码?这里做了什么新的事情,还是只是我已经做的事情的“更简单”的语法糖?


TL;DR

这绝对是新事物,它不仅仅是避免复制内存的一种方法。

长答案:为什么它是新的以及一些可能不明显的影响

移动语义正如其名称所暗示的那样——即一种显式声明用于移动对象而不是复制的指令的方法。除了明显的效率优势之外,这还为程序员提供了一种符合标准的方式来获取对象可移动但不可复制。可移动且不可复制的对象通过标准语言语义传达了非常清晰的资源所有权边界。这在过去是可能的,但没有标准/统一(或 STL 兼容)的方法来做到这一点。

这是一件大事,因为拥有标准和统一的语义对程序员和编译器都有好处。程序员不必花费时间将错误引入到可以由编译器可靠生成的移动例程中(大多数情况);编译器现在可以进行适当的优化,因为该标准提供了一种方法来通知编译器您何时何地进行标准移动。

移动语义特别有趣,因为它非常适合 RAII 习惯用法,这是 C++ 最佳实践的长期基石。 RAII 不仅仅包含这个示例,但我的观点是,移动语义现在是一种标准方法,用于简洁地表达(除其他外)可移动但不可复制的对象。

您不必总是显式定义此功能以防止复制。称为的编译器功能“复制省略”将从按值传递的函数中消除大量不必要的副本。

RAII 的刑事不完整速成课程(针对新手)

我知道您没有要求提供代码示例,但这里有一个非常简单的代码示例,可能会使未来的读者受益,他们可能不太熟悉该主题或移动语义与 RAII 实践的相关性。 (如果您已经了解这一点,请跳过本答案的其余部分)

// non-copyable class that manages lifecycle of a resource
// note:  non-virtual destructor--probably not an appropriate candidate
//        for serving as a base class for objects handled polymorphically.
class res_t {
  using handle_t = /* whatever */;
  handle_t* handle;  // Pointer to owned resource
public:
  res_t( const res_t& src ) = delete;            // no copy constructor
  res_t& operator=( const res_t& src ) = delete; // no copy-assignment

  res_t( res_t&& src ) = default;                // Move constructor
  res_t& operator=( res_t&& src ) = default;     // Move-assignment

  res_t();                                       // Default constructor
  ~res_t();                                      // Destructor
};

此类的对象将在构造时分配/提供所需的任何资源,然后在销毁时释放/释放它。由于数据成员所指向的资源永远不会意外地转移到另一个对象,因此资源的合法所有者永远不会受到怀疑。除了使您的代码不易被滥用或出错(并且易于与 STL 容器兼容)之外,您的意图将立即得到认可由任何熟悉此标准实践的程序员编写。

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

C++11 移动语义是在做一些新的事情,还是只是让语义更清晰? 的相关文章

  • 是否可以使用“git gc”来打包引用日志对象?

    正如答案所暗示的https stackoverflow com a 32025729 https stackoverflow com a 32025729我已经配置了远程裸仓库 git config gc pruneExpire never
  • 确保 StreamReader 不会挂起等待数据

    下面的代码读取从 tcp 客户端流读取的所有内容 并且在下一次迭代中它将仅位于 Read 上 我假设正在等待数据 我如何确保它不会在没有任何内容可供读取时返回 我是否必须设置低超时 并在失败时响应异常 或者有更好的办法吗 TcpClient
  • 提交后禁用按钮

    当用户提交付款表单并且发布表单的代码导致 Firefox 中出现重复发布时 我试图禁用按钮 去掉代码就不会出现这个问题 在firefox以外的任何浏览器中也不会出现这个问题 知道如何防止双重帖子吗 System Text StringBui
  • MVC 在布局代码之前执行视图代码并破坏我的脚本顺序

    我正在尝试将所有 javascript 包含内容移至页面底部 我正在将 MVC 与 Razor 一起使用 我编写了一个辅助方法来注册脚本 它按注册顺序保留脚本 并排除重复的内容 Html RegisterScript scripts som
  • 在 C 中匹配二进制模式

    我目前正在开发一个 C 程序 需要解析一些定制的数据结构 幸运的是我知道它们是如何构造的 但是我不确定如何在 C 中实现我的解析器 每个结构的长度都是 32 位 并且每个结构都可以通过其二进制签名来识别 举个例子 有两个我感兴趣的特定结构
  • 当我们想要返回对象的引用时,为什么我们在赋值运算符中返回 *this 而通常(而不是 this)?

    我正在学习 C 和指针 我以为我理解了指针 直到我看到这个 一方面 asterix 运算符是解引用的 这意味着它返回值所指向的地址中的值 而与号 运算符则相反 它返回值存储的地址记忆 现在阅读有关赋值重载的内 容 它说 我们返回 this因
  • 复制目录内容

    我想将目录 tmp1 的内容复制到另一个目录 tmp2 tmp1 可能包含文件和其他目录 我想使用C C 复制tmp1的内容 包括模式 如果 tmp1 包含目录树 我想递归复制它们 最简单的解决方案是什么 我找到了一个解决方案来打开目录并读
  • 单个对象的 Monogame XNA 变换矩阵?

    我读过一些解释 XNA Monogame 变换矩阵的教程 问题是这些矩阵应用于 SpriteBatch Begin matrix 这意味着所有 Draw 代码都将被转换 如何将变换矩阵应用于单个可绘制对象 就我而言 我想转换滚动背景 使其自
  • 为什么 Google 测试会出现段错误?

    我是 Google Test 的新手 正在尝试提供的示例 我的问题是 当我引入失败并设置GTEST BREAK ON FAILURE 1 或使用命令行选项 GTest 将出现段错误 我正在考虑这个例子 https code google c
  • 使用接口有什么好处?

    使用接口有什么用 我听说它用来代替多重继承 并且还可以用它来完成数据隐藏 还有其他优点吗 哪些地方使用了接口 程序员如何识别需要该接口 有什么区别explicit interface implementation and implicit
  • 在 C 中初始化变量

    我知道有时如果你不初始化int 如果打印整数 您将得到一个随机数 但将所有内容初始化为零似乎有点愚蠢 我问这个问题是因为我正在评论我的 C 项目 而且我对缩进非常直接 并且它可以完全编译 90 90 谢谢 Stackoverflow 但我想
  • 从 Linux 内核模块中调用用户空间函数

    我正在编写一个简单的 Linux 字符设备驱动程序 以通过 I O 端口将数据输出到硬件 我有一个执行浮点运算的函数来计算硬件的正确输出 不幸的是 这意味着我需要将此函数保留在用户空间中 因为 Linux 内核不能很好地处理浮点运算 这是设
  • 具有交替类型的可变参数模板参数包

    我想知道是否可以使用参数包捕获交替参数模式 例如 template
  • Qt - ubuntu中的串口名称

    我在 Ubuntu 上查找串行端口名称时遇到问题 如您所知 为了在 Windows 上读取串口 我们可以使用以下代码 serial gt setPortName com3 但是当我在 Ubuntu 上编译这段代码时 我无法使用这段代码 se
  • 为什么 std::strstream 被弃用?

    我最近发现std strstream已被弃用 取而代之的是std stringstream 我已经有一段时间没有使用它了 但它做了我当时需要做的事情 所以很惊讶听到它的弃用 我的问题是为什么做出这个决定 有什么好处std stringstr
  • 无法接收 UDP Windows RT

    我正在为 Windows 8 RT 编写一个 Windows Store Metro Modern RT 应用程序 需要在端口 49030 上接收 UDP 数据包 但我似乎无法接收任何数据包 我已按照使用教程进行操作DatagramSock
  • Oracle Data Provider for .NET 不支持 Oracle 19.0.48.0.0

    我们刚刚升级到 Oracle 19c 19 3 0 所有应用程序都停止工作并出现以下错误消息 Oracle Data Provider for NET 不支持 Oracle 19 0 48 0 0 我将 Oracle ManagedData
  • 使用 .NET Process.Start 运行时挂起进程 - 出了什么问题?

    我在 svn exe 周围编写了一个快速而肮脏的包装器来检索一些内容并对其执行某些操作 但对于某些输入 它偶尔会重复挂起并且无法完成 例如 一个调用是 svn list svn list http myserver 84 svn Docum
  • 当从finally中抛出异常时,Catch块不会被评估

    出现这个问题的原因是之前在 NET 4 0 中运行的代码在 NET 4 5 中因未处理的异常而失败 部分原因是 try finallys 如果您想了解详细信息 请阅读更多内容微软连接 https connect microsoft com
  • 当我使用 OpenSSL1.1.0g 根据固定的 p 和 g 值创建 Diffie Hellman 密钥协议密钥时,应该执行哪些检查?

    您好 我尝试通过这段代码使用修复 p 和 g 参数来制作 Diffie Hellman Keysanswer https stackoverflow com a 54538811 4706711 include

随机推荐

  • ActionResult AcceptVerbsAttribute 默认 HTTP 方法有哪些?

    我知道您可以通过添加 AcceptVerbsAttribute 来限制特定 ActionResult 方法响应哪些 HTTP 方法 例如 AcceptVerbs HttpVerbs Get public ActionResult Index
  • 从 UIPageViewController 中删除视图控制器

    奇怪的是没有直接的方法来做到这一点 考虑以下场景 您有一个包含 1 页的页面视图控制器 添加另一个页面 共 2 个 并滚动到该页面 我想要的是 当用户滚动回到第一页时 第二页现在被删除并释放 并且用户无法再滑回该页面 我尝试在转换完成后将视
  • 如何计算 luxon 中两个日期之间的持续时间?

    Luxon s 的文档Duration fromISO method https moment github io luxon docs class src duration js 7EDuration html static method
  • HTML - 按钮 - 如何使其可链接?

    我有一个像这样的按钮
  • Ubuntu Github ssh 密钥问题

    我遵循了本指南中给出的每个步骤 http help github com linux key setup http help github com linux key setup 当我读到最后时 我可以 ssh 到 电子邮件受保护 cdn
  • Node JS:从树 json 制作平面 json

    我正在编写一个 node js 脚本来组合目录中的所有 json 文件并将结果存储为新的 json 文件 我尝试在很大程度上完成这项工作 但它有一些缺陷 A json id addEmoticon1 description Message
  • C64 组件 - 6502/6510 - 依次显示一系列三个位图,然后进入字符模式

    我这里有一个很大的问题 我发现仅靠几本参考书 互联网和你的真实资料很难回答这个问题 我只想显示一个位图 等几秒钟 把它从记忆中抹去 显示另一个位图 再等一下 把那个从记忆中抹掉 显示最终位图 等最后一次吧 而且 你已经猜到了 把它从记忆中抹
  • Chrome 切换到 OSX 通知后,网络推送通知未显示

    由于 Chrome 切换到本机 OSX 通知 有时我尝试使用网络推送和我的 Service Worker 显示的通知不会出现 它们在 Chrome 的早期版本中一致出现 自从他们开始做这项工作以来 我应该改变什么吗 确保 请勿打扰 已关闭
  • 快速字符串替换

    在构建了一个可能非常大的字符串后 我将对其进行大量更改 将其中的单个字符 或字节 如果需要 更改为另一个字符 实际上 我的脚本正在构建一个填字游戏 因此字符串不会很长 但我的问题很笼统 我如何利用我不改变字符串 或任何更好的数据类型 长度的
  • 如何增加 UIButton 的点击区域?

    I use UIButton具有自动布局 当图像较小时 点击区域也较小 我可以想象几种方法来解决这个问题 增加图像尺寸 即在图像周围放置透明区域 这不好 因为当您定位图像时 您必须记住额外的透明边框 使用 CGRectInset 并增加大小
  • 在 Solaris 上构建 Node.JS:“使用 仅在 c99 编译环境中有效。”

    我正在尝试在 Solaris 上安装 Node JS 这是开箱即用的 Solaris 9 10 x86 最新版本是 2010 年 9 月 并且仅使用默认软件包 我遵循的方向在这里 https github com joyent node w
  • 在Android 4.0.3中设置textview淡入淡出

    我刚刚尝试实现淡入淡出效果TextView在安卓4 0 3中 然而 它不起作用 fadingEdge horizontal singleLine true ellipsize marquee 此代码适用于 2 3 7 及以下版本 但不适用于
  • Dart 作为 Worker 进行隔离

    编辑以使问题更清楚 我正在尝试在 Dart 中使用 Isolates 或 Web Workers 我能找到在主线程和隔离线程之间进行通信的唯一方法是send and 打电话然后从主线程 但这是主线程将一些数据传递给隔离的好方法 如果我希望分
  • GitHub 推送错误 - “git 媒体更新”

    我一直在使用 GitHub for Mac 客户端 两个月来它一直工作得很好 昨天 成功提交和推送后 我的客户端自行关闭然后重新启动 从那时起 我就无法将更改推送到我的在线存储库 在客户端中 我收到消息 git media pre push
  • 在Sikuli拍照的命令是什么

    我正在使用 Sikuli IDE 我想知道截屏的命令是什么 这样我就可以在测试结束时捕获屏幕 像这样的东西 try if bla bla bla print blablabla else TAKESCREENSHOT gt What com
  • 在 stripes actionbean 中绑定隐藏字段时,隐藏字段变为 null

    我有一个条纹操作页面 当页面加载时 我想通过从对象 即 setOriginalAssignee userAction getAssignee 分配原始Assignee 来保存它 这样 如果对象的字段受让人发生更改 我将进行一些计算 这是我的
  • 计算根的父母拥有的百分比

    简而言之 我试图计算树的父级所拥有的树根的百分比 即树的更上层 我怎样才能单独用 SQL 来做到这一点 这是我的 示例 架构 请注意 虽然层次结构本身非常简单 但还有一个附加的holding id 这意味着单亲父母可以 拥有 孩子的不同部分
  • 如何使用 SymPy codegen 生成 Fortran 子例程

    我想使用 SymPy codegen 实用程序生成 Fortran 子例程 我可以毫无问题地生成 Fortran 函数codegen f x y z f95 filename 但我想生成一个 Fortran 子例程 以便可以修改输入数组 我
  • 将 ZedGraph 中的 DateAsOrdinal xAxis 标签格式化

    我现在已经改变了我的x axis to 日期为序号 但我想改进标签格式 我目前处理的是XAxis ScaleFormatEvent像这样 Private Function OnXScaleFormatEvent ByVal pane As
  • C++11 移动语义是在做一些新的事情,还是只是让语义更清晰?

    我基本上想弄清楚 整个 移动语义 概念是全新的 还是只是使现有代码更易于实现 我总是对减少调用复制 构造函数的次数感兴趣 但我通常使用引用 可能还有 const 来传递对象 并确保我始终使用初始化列表 考虑到这一点 并查看了整个丑陋的 语法