如何通过move语义移动多个参数

How do I move multiple parameter via Move semantics?

本文关键字:参数 移动 语义 何通过 move      更新时间:2023-10-16

让我们假设我有一个Object MeasurementValues,它有n个不同的指针(这个例子只显示了指向基元类型的指针,但也可能出现指向其他复杂对象的指针(。

class MesaurementValues {
   private:
     int *measurement_1;
     double *measurement_2;
     long long *measurement_3;
     //..
     float *measurement_n;
     int noPointer;
}

我知道,无论如何,这个例子可能有点做作。我试图在我的代码中完全填充"五条规则"。

我必须吗

this.measurement_x = old.measurement_x ;// for all x = {1,..,n} ?

首先要注意,对于普通的旧数据类型(POD(成员,移动语义与复制语义相比没有优势,但当您的类包含其他类对象和/或数组时,它确实有优势。当你实现移动语义时,这意味着你有一个"移动构造函数"和/或"移动赋值运算符",在你的类中看起来像这样:

class MesaurementValues { private:
     int *measurement_1;
     double *measurement_2;
     long long *measurement_3;
     //..
     float *measurement_n;
     int noPointer; 
     //a couple different objects
     someObject*       pObj1;
     differentObject*  pObj2;
 public:
  MeasurementValues( MeasurementValues&& move );  //move-constructor
  MeasurementValues& operator= (MeasurementValues&& move); //move-assignment
}

-假设您的类具有POD数据和类对象,并且-假设有很多变量需要转移:

MeasurementValues::MeasurementValues( MeasurementValues&& old) {
    //copy plain-old-data over
    measurement_1 = old.measurement_1;
    measurement_2 = old.measurement_2;
    //copy over values of the pointers
    pObj1 = old.pObj1;
    pObj2 = old.pObj2;
}

请记住,正如其他海报所说,只有当您的数据成员是其他可移动对象或动态分配的内存时,移动语义才有优势。

编辑:

中的指针必须变为"无效",因为它们已被移动。因此,我会将它们设置为null,以防止出现意外行为:

MeasurementValues::MeasurementValues( MeasurementValues&& old) 
: measurement_1() //null...
  //,...
{
  //Swapping null into old...
  std::swap(measurement_1, old.measurement_1);
  //...
}
Do I have to
this.measurement_x = old.measurement_x ;// for all x = {1,..,n} ?

我会使用皮条客这个成语,并使用一个独特的指针。下面是一个详细的例子。请注意,您只需要使用Impl,并依赖于它的默认值(因为它不包含指针(。

#include <iostream>
#include <memory>
struct Moveable
{
  public:
    Moveable();
    ~Moveable();
    Moveable(const Moveable& m);
    Moveable& operator=(const Moveable& m);
    Moveable(Moveable&& m);
    Moveable& operator=(Moveable&& m);
    int foo() const;

  private:
    struct Impl;
    std::unique_ptr<Impl> pimpl_;
};
//Moveable.cpp
struct Moveable::Impl
{
  Impl(): a(1), b(2), c(3), buffer(){}
  int a, b, c;
  char buffer[10000]; //Make it worth our while...
};
int Moveable::foo() const{ return pimpl_->a+pimpl_->b+pimpl_->c;}
Moveable::Moveable()
: pimpl_(new Impl)
{
  std::cout << "Default " << (void*)this << std::endl;
}
Moveable::~Moveable()
{
  std::cout << "Destruct " << (void*)this << std::endl;
  //automagically...
}
Moveable::Moveable(const Moveable&m)
: pimpl_(new Impl(*m.pimpl_))
{
  std::cout << "Copying " << &m << " to " << (void*)this << std::endl;
}
Moveable& Moveable::operator=(const Moveable& m)
{
  std::cout << "Copy assign " << (void*)&m << " to " << (void*)this << std::endl;
  *pimpl_ = *m.pimpl_; //Relying on their defaults...
}
Moveable::Moveable(Moveable&& m)
: pimpl_(move(m.pimpl_))
{
  std::cout << "Moving " << (void*)&m << " to " << (void*)this << std::endl;
}
Moveable& Moveable::operator=(Moveable&& m)
{
  pimpl_ = move(m.pimpl_);
  std::cout << "Move assigning " << &m << " to " << (void*)this << std::endl;
}
int main() 
{
  Moveable x;
  Moveable y(x); //Copying...
  y = x; //Copying assign
  y = Moveable(); //Default construct, then move assignment, destruct temp
  Moveable z(std::move(y));
  std::cout << "Calling foo " << z.foo() << std::endl;
  return 0;
}