【问题标题】:c++ : move assignement operator and inheritancec++:移动赋值运算符和继承
【发布时间】:2020-12-15 06:46:04
【问题描述】:

这段代码编译运行良好:

#include <iostream>

class Base
{
  public:
  Base(int value)
  : clean_(true)
  {
      value_ = new int;
      *value_ = value;
  }
  ~Base()
  {
      if(clean_)
        delete value_;
  }
  Base(Base&& other) noexcept 
  : value_{std::move(other.value_)},
    clean_(true)
  {
      other.clean_=false;
  }
  Base& operator=(Base&& other) noexcept
  {
      value_ = std::move(other.value_);
      other.clean_=false;
      clean_=true;
  }
  void print()
  {
      std::cout << value_ << " : " << *value_ << std::endl;
  }
  
  int* value_;
  bool clean_;
    
};

class A : public Base 
{
  public:
  A(int v1, double v2) : Base(v1)
  {
      a_ = new double;
      *a_ = v2;
  }
  A(A&& other) noexcept
  : Base(std::forward<Base>(other)),
    a_(std::move(other.a_))
  {}
  A& operator=(A&& other) noexcept
  {
      // should not the move assignment operator
      // of Base be called instead ? 
      // If so: how ?
      this->value_ = std::move(other.value_);
      other.clean_=false;
      this->clean_=true;
      a_ = std::move(other.a_);
  }
  void print()
  {
      std::cout << this->value_ << " "
                << *(this->value_) << " "
                << a_ << " " << *a_ << std::endl;
  }

  double* a_;
  bool clean_;
    
};

A create_a(int v1,double v2)
{
    A a(v1,v2);
    return a;
}

int main()
{
    Base b1(20);
    b1.print();
    
    Base b2 = std::move(b1);
    b2.print();
    
    A a1(10,50.2);
    a1.print();
    
    A a2 = std::move(a1);
    a2.print();
    
    A a3 = create_a(1,2);
    a3.print();
}

A 是 Base 的子类。

A 的移动赋值运算符的代码复制了 Base 的代码。

有没有办法避免这种代码复制?

【问题讨论】:

  • 使用unique_ptr&lt;int&gt;,根本不写这些方法?
  • 您是否打算在 A 类型的对象中拥有两个 clean_ 副本?
  • 请注意:您知道std::move 不执行移动,而只是一个演员表?所以a_ = std::move(other.a_); 没有多大意义,因为a_ 只是一个指针。
  • @t.niese 确保我明白了,你的意思是 a_=std::move(other.a_) 相当于 a_ = other.a_ ?
  • 对于显示的代码,其结果是等效的。 std::move 只是对r-value 的强制转换,other.a_ 的值将在给定情况下的两种情况下被复制。所以在这种情况下你可以写a_ = other.a_

标签: c++ inheritance move-semantics assignment-operator


【解决方案1】:

int* value_; 更改为int value_; 并将double* a_; 更改为double a_;,您不再需要编写任何特殊的成员函数,因为编译器提供了默认的Just Work™

如果您确实需要动态内存分配,请使用RAII type,例如std::vectorstd::unique_ptrstd::shared_ptr 等。取而代之,因为它们被设计为可以正确复制和/或移动。

【讨论】:

  • 对于这个特定的示例,这是有道理的,但这只是一些用于使问题清晰的最小代码。你如何调用 Base 类的移动赋值运算符,考虑到这个最新的并不像这里举例说明的那么简单?
  • @Vince 诀窍是使用 RAII 类型。然后你不需要做任何事情,正确的行为就会提供给你。如果你真的想调用基类的移动赋值,那么Base::operator=(std::move(other));会调用基类的移动赋值运算符。
  • 感谢您的回答,这有效! (我的原始代码是在操作指向一些进程间共享内存的指针。)
猜你喜欢
  • 2018-11-24
  • 1970-01-01
  • 2021-06-07
  • 1970-01-01
  • 2012-02-28
  • 2015-02-09
  • 2021-08-28
  • 1970-01-01
  • 2011-08-12
相关资源
最近更新 更多