在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'。
答案 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中分配的双打。