RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1308884
Accepted
ArtemiiSelyankin
ArtemiiSelyankin
Asked:2022-07-26 10:28:56 +0000 UTC2022-07-26 10:28:56 +0000 UTC 2022-07-26 10:28:56 +0000 UTC

覆盖正在移动的类对象的所有字段是否值得

  • 772

我有一堂课:

template<class T>
class IdRange
{
    T var1_;
    ...
    T var6_;

    T start_;
    T step_;

public:
    IdRange(T start = 0, T step = 1) { ... }

    IdRange(IdRange&& other)
        : var1_ (std::move(other.var1_)),
          ...
          var6_ (std::move(other.var6_)),
          start_(std::move(other.start_)),
          step_ (std::move(other.step_))
    {
        Как сделать здесь?
    }
}

(通过“覆盖”我的意思是分配一个默认值。这么短。)

情况是这样的。有不同的字段,我将它们指定为T var1_; ... T var6_;. 一切都很清楚,我将它们从other转移到this并在other中覆盖它们,但也有start_和step_。首先,他们也应该像其他人一样被转移。但那该怎么办呢。start_和step_仅在创建对象时设置,之后无法更改。在这种情况下该怎么办:

  • 覆盖其他字段,但不要覆盖start_和step_。
  • 擦拭一切。
  • 因此,对此没有任何规定,您可以随心所欲。

和一点澄清。

IdRange(IdRange&& other)
    : var1_ (std::move(other.var1_)),
      ...
      var6_ (std::move(other.var6_)),
      start_(std::move(other.start_)),
      step_ (std::move(other.step_))
}

值得写std::move吗?我不去哪个站点,这里没有人使用它们,没有它们,就会调用复制构造函数,因此调试器会显示是否有任何内容。

c++
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    AlexGlebe
    2022-07-26T20:02:32Z2022-07-26T20:02:32Z

    移动对象时,只需要在想要摆脱双重所有权问题时覆盖边距。例如,作为指针的字段指向分配的内存区域。并且当调用一个析构函数时,第二个对象将被剥夺数据,第二次删除内存将导致内存错误。

    这一切都取决于算法和场的原理。可能存在整数索引可以用作某些内存区域所有权的标志的选项。然后这些索引应该被重置为零,这样就没有双重所有权。

    该命令std::move是类型转换的简化static_cast<C&&>(..)。如果内部变量的值应该转移到另一个对象,则应该使用它。但是当调用移动构造函数时,简单类型通常不会无效,程序员应该手动执行此操作。

    带指针的示例:

    class C{
    public:
        C(C&&c):
          // указатель это простой тип, и при перемещении не обнуляется
          // использовать std::move не имеет смысла
          ar{c.ar},
          // то-же самое
          si{c.si}{
            // затирание у аргумента нужно делать вручную
            c.ar = nullptr ;
            c.si = 0 ; }
    private:
        int * ar ;
        size_t si ;
    };
    

    如果您有一个具有模板化内部类型的类,您应该使用std::move通用行为,并且如果在简单类型(例如指针)上调用移动构造函数,则从外部内存源的所有权手动调用清理函数。

    template<class T>
    void IdRangeInit( T & );
    
    IdRange(IdRange&& other)
        : var1_ (std::move(other.var1_)),
          ...
          var6_ (std::move(other.var6_)),
          start_(std::move(other.start_)),
          step_ (std::move(other.step_))
    {
        IdRangeInit<T>(other.var1_);
        ...
        IdRangeInit<T>(other.var6_);
        IdRangeInit<T>(other.start_);
        IdRangeInit<T>(other.step_);
    }
    
    template<>
    void IdRangeInit( size_t & i ){ 
      i = 0 ; }
    
    template<>
    void IdRangeInit( int * & i ){ 
      i = nullptr ; }
    
    // Если какой-то класс после перемещения уже пустой,
    // то ничего больше делать не надо
    template<>
    void IdRangeInit( BigClass & b ) {
      }
    
    • 2
  2. HolyBlackCat
    2022-07-27T01:29:20Z2022-07-27T01:29:20Z

    粗略地说,有两种类:

    • 有些需要自定义析构函数来复制和/或移动构造函数和赋值运算符,因为它们直接拥有某些资源(或其他原因)。

    • 谁不需要这些,他们不拥有任何东西。

    大多数是后者。

    在您的课程中,我没有在移动构造函数中看到任何特殊逻辑,因此您可能应该遵循零规则,而不是编写移动构造函数或其他列出的操作。

    这将导致它们被移动的对象的字段不会被清空,这对于第二类的类是正常的。您不会为每个小结构手动编写所有 5 个操作来实现此归零。

    第一类中的类通常需要取消所有内容(或做类似的事情)。想象一下,如果std::vector在移动时,指向缓冲区的指针会归零(没有这个,无论如何),但大小不会。这会很糟糕。

    • 1

相关问题

  • 编译器和模板处理

  • 指针。找到最小数量

  • C++,关于枚举类对象初始化的问题

  • 函数中的二维数组

  • 无法使用默认构造函数创建类对象

  • C++ 和循环依赖

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    表格填充不起作用

    • 2 个回答
  • Marko Smith

    提示 50/50,有两个,其中一个是正确的

    • 1 个回答
  • Marko Smith

    在 PyQt5 中停止进程

    • 1 个回答
  • Marko Smith

    我的脚本不工作

    • 1 个回答
  • Marko Smith

    在文本文件中写入和读取列表

    • 2 个回答
  • Marko Smith

    如何像屏幕截图中那样并排排列这些块?

    • 1 个回答
  • Marko Smith

    确定文本文件中每一行的字符数

    • 2 个回答
  • Marko Smith

    将接口对象传递给 JAVA 构造函数

    • 1 个回答
  • Marko Smith

    正确更新数据库中的数据

    • 1 个回答
  • Marko Smith

    Python解析不是css

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5