这个C ++移动构造函数中是否存在内存泄漏?

时间:2016-07-21 16:24:25

标签: c++ memory-leaks move-constructor

在Stroustrups C ++编程语言第四版,第76页,有移动构造函数使用的示例。

该类的定义如下:

class Vector { 
private: 
  double∗ elem; // elem points to an array of sz doubles 
  int sz; 
public: 
  Vector(int s) :elem{new double[s]}, sz{s} 
  { for (int i=0; i!=s; ++i) elem[i]=0; // initialize elements } 

  ~Vector() { delete[] elem; } // destructor: release resources 
  Vector(const Vector& a); // copy constructor 
  Vector& operator=(const Vector& a); // copy assignment 
  Vector(Vector&& a); // move constructor 
  Vector& operator=(Vector&& a); // move assignment 

  double& operator[](int i); 
  const double& operator[](int i) const; 
  int size() const; 
}; 

定义了移动构造函数:

Vector::Vector(Vector&& a) :elem{a.elem}, // "grab the elements" from a 
  sz{a.sz} 
{ 
  a.elem = nullptr; // now a has no elements 
  a.sz = 0; 
} 

我认为会导致内存泄漏的示例执行:

Vector f() 
{ 
  Vector x(1000); 
  Vector y(1000); 
  Vector z(1000); 
  // ... 
  z=x; //we get a copy 
  y = std::move(x); // we get a move 
  // ... 
  return z; //we get a move 
}; 

似乎这样的移动操作会导致内存泄漏,因为y已在

中分配了1000个元素
Vector y(1000); 

和第y行的简单指针重新赋值= std :: move(x);将剩下的这些最初的1000个整数留给自己。我假设,移动构造函数必须有额外的代码行才能在移动之前取消分配指针'elem'。

4 个答案:

答案 0 :(得分:2)

假设移动构造函数正确实现,没有。您引用的行调用移动赋值,而不是构造函数,因为z已经存在。

答案 1 :(得分:2)

  

这个C ++移动构造函数中是否存在内存泄漏?

没有

  

我认为会导致内存泄漏的示例执行:

显示的执行调用移动赋值,而不是移动构造函数。

  

我假设,移动构造函数必须有额外的代码行才能在移动之前取消分配指针'elem'。

它不需要,因为新构造的对象的指针在使用move参数的指针值初始化之前不能指向任何已分配的内存。

答案 2 :(得分:0)

是的,同意,这是移动赋值:y = std :: move(x);,而不是构造函数。 在书中他们没有表明,只是提到移动分配的定义相似。 但是,在移动分配定义中,据我所知,我们需要释放elem,对吧?这样的事情。

Vector& Vector::operator=(Vector&& a)
{ 
  delete[] elem;
  elem = a.elem;
  sz = a.sz;
  a.elem = nullptr; // now a has no elements 
  a.sz = 0; 
}

答案 3 :(得分:0)

  

和第y行的简单指针重新赋值= std :: move(x);会离开   这些最初的1000个整数由y指出。

指向double的指针的地址被复制到新对象(y),旧对象(x)将其指针设置为nullptr。 (它未在移动分配方法中发生)

  

我假设,移动构造函数必须有额外的代码行   取消分配指针' elem'在移动之前。

此处不需要解除分配。指针只是被移动了#39;在任务期间(它也将在移动施工期间移动)。双指针的清理应该由析构函数处理。在x的情况下,析构函数最终会在nullptr上触发。删除nullptr上的[]是一个noop。见http://www.cplusplus.com/reference/new/operator%20delete[]/

然而,如所指出的那样,在移动分配期间需要清除在y中分配的双打。