说我有一个班级
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
现在将指向无效的内存空间。
答案 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
}