当源obj被销毁时,使用move cstor会丢失内存吗?

时间:2015-10-28 23:39:15

标签: c++ c++11 constructor move-semantics move-constructor

说我有一个班级

MyClass {
  //.. cstors and dstor
  void MyClass(MyClass&& source) : some_obj_(std::move(source.some_obj_));
  SomeObj some_obj_;
}

说我做了以下事情:

// a1 is defined somewhere else with a wider scope
MyClass a1; 
...
// a2 is defined locally and will go out of scope soon
MyClass a2; 
... //Populate a2's some_obj_ field with data
a1 = std::move(a2); // move instead of copy

在这种情况下,将调用move构造函数。根据我的理解,移动构造函数交换两者之间的字段指针,以便不会发生复制。

所以这是我的问题。实例化a2时,它会在a2内为字段some_obj_分配内存。当移动发生时,我们交换指针,以便现在a1的{​​{1}}指向some_obj_持有的内存块(而不是在其自己的内存空间上复制它) )。将来,当a2超出范围时,例如包含a2的函数返回以清除堆栈帧,因为a2位于a2.some_obj_内,它也会被删除。由于移动后a2指向已经清理过的a1.some_obj_内存,a2会丢失那部分信息吗?

似乎遵循上述逻辑,a1现在将指向无效的内存空间。

2 个答案:

答案 0 :(得分:2)

以下是移动类的典型实现

template<typename T>
struct moving
{
  moving()=default;
  explicit moving(size_t n)
  : ptr(new T[n]) {}
  moving(moving const&)=delete;
  moving&operator=(moving const&)=delete;
  moving(moving&&m)
  : ptr(m.ptr) { m.ptr=nullptr; }
  moving&operator=(moving&&m)
  { if(this!=&m) { delete ptr; ptr=m.ptr; m.ptr=nullptr; } return*this; }
private:
  T*ptr=nullptr;
};

所以你可以自己弄清楚会发生什么。

请注意,移动语义仅与管理外部资源的情况相关(例如,指向已分配内存的地址的指针或某些类型的库管理资源(如HDF5 ID)的句柄)。对于其他普通数据,移动与复制没有什么不同。

答案 1 :(得分:1)

如果正确实现了移动构造函数,则不会泄漏任何内存。特别是,典型的移动构造函数将rhs指针设置为nullptr,因此移动对象的析构函数中的后续delete是无操作。超简化示例:

X::X(X&& rhs)
{
    this->p = rhs.p; // here p is a pointer
    rhs.p = nullptr; // now the delete p from the dtor of rhs is a no-op
}