隐式移动与复制操作和遏制

2023-11-30

当类有一个未定义移动操作的成员时,我很难理解隐式移动操作:

int main() {
    struct A // no move: move = copy
    {
        A() = default;
        A(const A&) {
            cout << "A'copy-ctor\n";
        };
        A& operator=(const A&) {
            cout << "A'copy-assign\n";
            return *this;
        }
    };

    struct B
    {
        B() = default;
        A a; // does this make B non-moveable?
        unique_ptr<int> upi;
        // B(B&&) noexcept = default;
        // B& operator=(B&&)noexcept = default;
    };

    A a;
    A a2 = std::move(a); // ok use copy ctor instead of move one
    a2 = std::move(a); // ok use copy assignment instead of move one

    B b;
    B b2 = std::move(b); // why this works?
    b = std::move(b2); // and this works?
    // b = b2; // error: copy deleted because of non-copyable member upi

    cout << "\nDone!\n";
}

所以我看到的是A是一个不可移动的类,因为它定义了复制控制操作,因此它只能被复制,并且任何试图移动此类对象的操作都会使用相应的复制操作。

到这里为止,如果我是正确的就可以了。但B有一个不可复制的对象upi这是一个unique_ptr因此复制操作被定义为删除函数,因此我们无法复制此类的对象。但是这个类有一个不可移动的对象a因此我认为这门课(B) 既不可复制也不可移动。但为什么要初始化b2和分配b工作正常?到底发生了什么?

B b2 = std::move(b); // ok?!

为什么上面的行调用类的复制构造函数A它是否调用移动构造函数B?

  • 事情对我来说变得更糟:如果我取消注释移动操作行B,上面的初始化不会编译并抱怨引用已删除的函数,对于赋值也是如此!

谁能帮我看看究竟发生了什么?在在这里发布问题之前,我已经用谷歌搜索并阅读了 cppreference 和许多网站。

输出:

A'copy-ctor
A'copy-assign
A'copy-ctor
A'copy-assign

Done!

请记住在 C++ 中“移动”数据意味着什么(假设我们遵循通常的约定)。如果你移动物体x反对y, then y接收其中的所有数据x and x是...好吧,我们不在乎什么x只要它仍然有效即可销毁。很多时候我们会想到x丢失所有数据,但这不是必需的。所需要的只是x已验证。如果x最终得到相同的数据y,我们不在乎。

Copying x to y causes y接收其中的所有数据x, and x保持有效状态(假设复制操作遵循约定并且没有错误)。因此,复制算作移动。除了复制操作之外还定义移动操作的原因不是为了允许新的东西,而是为了在某些情况下允许更高的效率。任何可复制的内容都可以移动,除非您采取措施阻止移动。

所以我看到的是A是一个不可移动的类,因为它定义了复制控制操作,因此它只能被复制,并且任何试图移动此类对象的操作都会使用相应的复制操作。

我看到的是A is a moveable类(尽管缺少移动构造函数和移动赋值),因为它定义了复制控制操作。任何移动此类对象的尝试都将依赖于相应的复制操作。如果您希望一个类可复制但不可移动,则需要删除移动操作,同时保留复制操作。(尝试一下。添加A(A&&) = delete;按照你的定义A.)

The B类有一个可以移动或复制的成员,以及一个可以移动但不能复制的成员。所以B本身可以移动但不能复制。什么时候B被移动,则unique_ptr成员将按照您的预期移动,并且A成员将被复制(移动类型对象的后备A).


事情对我来说变得更糟:如果我取消注释移动操作行B,上面的初始化不会编译并抱怨引用已删除的函数,对于赋值也是如此!

更仔细地阅读错误消息。当我复制此结果时,“使用已删除函数”错误后面跟着一条提供更多详细信息的注释:移动构造函数已被删除,因为“其异常规范与隐式异常规范不匹配”。删除noexcept关键字允许代码编译(使用 gcc 9.2 和 6.1)。

或者,您可以添加noexcept到复制构造函数和复制赋值A(保持noexcept的移动操作B)。这是演示默认移动操作的一种方法B使用复制操作A.

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

隐式移动与复制操作和遏制 的相关文章

随机推荐

  • Javascript根据另一个下拉框值更改下拉框选项[重复]

    这个问题在这里已经有答案了 我正在练习 JavaScript 编程 我发现了一个问题 必须由一些专家来回答drop down boxes 场景是 我有一个drop down框提供了省份的一些可能选项以及第二个选项 城镇 该选项仅取决于省份中
  • 如何以层次结构显示非标准化数据?

    我的问题是我想以层次结构显示数据 如下所示 Democrat County Clerk 候选人1 候选人2 Magistrate 候选人1 候选人2 候选人3 但我正在检索这样的数据集 Party Office Candidate Demo
  • 当最终网址为 https 时,如何使用 python 取消缩短(解析)网址?

    当最终的 url 是 https 时 我希望在 python 中取消缩短 解析 一个 url 我看到过这样的问题 如何使用 python 取消缩短 URL 以及其他类似的 但是正如已接受答案的评论中所述 此解决方案仅在 url 未重定向到
  • 零填充矩阵

    我有一个 16X16 矩阵 我必须将它添加到 256X256 矩阵中 谁能帮助我如何将这个 16X16 矩阵变成 256X256 并用零填充剩余的矩阵 如果您将某些内容分配给超出原始大小的元素 Matlab 会自动用零填充 gt gt A
  • 根据下一行的格式删除换行符

    我有一个这种格式的特殊文件 title1 1 texthere title2 2 texthere 我希望将所有以 开头的换行符放置为之前行的第二列 我尝试使用 sed 和以下命令来做到这一点 sed s n g filename 但它没有
  • 使用 log4net 的 RichTextBoxAppender

    有没有办法使用 log4net 以编程方式创建 RichTextBox Appender 换句话说 没有 xml app config using System using System Windows Forms using System
  • 单击日历外部时,fullcalendar 触发事件单击

    我有一份活动日期清单 当我单击列表中的事件时 我想触发与单击日历相同的操作 我的事件点击函数 eventClick function calEvent jsEvent view openEvent calEvent 尝试这个 为您的事件分配
  • 在 Windows 中获取用户日期格式

    我的问题类似于this one 但是 我不想获取日期格式locale 而是由用户设置的 原因是我正在使用pywin32与 Outlook 通信的 api 特别是按日期过滤邮件 我必须将日期传递给应用程序的格式是用户设置的格式 否则它将无法工
  • MATLAB 类 getter 和 setter

    我有 Java 背景 我在 Matlab 中的类尤其是 getter 和 setter 方面遇到问题 收到一条消息说句柄和值类之间存在冲突我有点不知道该怎么做 所以任何缺乏更好的词的帮助都会有所帮助 classdef Person prop
  • MUI 自动完成 – 从 3 个字符开始过滤

    我有这样的 Autcomplete mui 组件 它可以对复选框列表进行过滤 带有选项的弹出窗口应始终保持打开状态 我需要做的是仅当用户输入超过 3 个字符时才触发过滤
  • 循环遍历maven中的特定资源文件生成源

    我使用 maven antrun plugin 从 thrift IDL 生成源代码 我有一个单独的项目 和 jar 来保存这些生成的源 并且这个插件不支持通配符替换 所以我不能说 thrift 我使用执行任务来生成源代码并将它们复制到 s
  • 使用 dplyr 填充缺失的序列值

    我有一个数据框 其中缺少 SNAP ID 值 我想根据之前的非缺失值 lag 的序列 用浮点值填充缺失值 如果可能的话 我真的很想仅使用 dplyr 来实现这一目标 假设 永远不会丢失数据 因为我根据数据集的最小和最大之间的缺失天数生成缺失
  • Android 模拟器复选框和单选按钮错误 - ui 上显示各种不正确的状态

    最近 我发现模拟器的显示单选按钮和复选框有奇怪的行为 它不是只有 2 种 UI 状态 更具体地说 它显示 4 种不同甚至更多 我想它们是冻结的动画状态 在布局检查器和新版本的 API 上 它看起来很正常 请看下面的图片 我在 Api 版本
  • python 中 time.sleep 的奇怪打印行为[重复]

    这个问题在这里已经有答案了 我试图通过在同一行上每秒打印一个点来创建一个类似进度的东西 比如 钓鱼 之类的 这是我用的 import time print Fishing end for i in range 5 time sleep 1
  • WPF 迭代数据网格

    使用 WPF C NET4 5 使用 Visual Studio 2012 ulti 旧的 winforms 代码 foreach DataGridViewRow paretoRow in ParetoGrid Rows if Conver
  • pygame 平台游戏 - 如何使底部坚固?

    所以我正在制作一个 pygame 平台游戏 但我被困在一件事上 我找不到一种方法来使我的平台底部变得坚固 玩家可以降落在其顶部 但当它试图穿过底部时 它会弹回下方 我尝试了这个但没有成功 hits pg sprite spritecolli
  • 通过C#反射获取类内Enum的类型

    我有一个像这样的枚举 namespace EnumTest public class Enumeration public Enumeration public enum Days day sunday night monday 我怎样才能
  • MongoDB oplog有键名带点的记录,无法查询,afaict

    鉴于 Mongo 允许使用 点 设置嵌套字段 例如 rs0 PRIMARY gt db tmp update a 1 set b c 2 upsert true rs0 PRIMARY gt db tmp findOne id Object
  • jQuery 自动完成@mention

    我有 Andrew Whitaker 的这个自动完成插件 DEMO假设我有一个字符串textarea 欢迎 peterwaterber 我希望它在隐藏标签中输出为 彼得沃特伯 欢迎 我该怎么办 我不太擅长Javascript 我尝试过查看这
  • 隐式移动与复制操作和遏制

    当类有一个未定义移动操作的成员时 我很难理解隐式移动操作 int main struct A no move move copy A default A const A cout lt lt A copy ctor n A operator