当源obj被销毁时,使用move-cst是否会丢失内存
Does using move cstor lose memory when the source obj is destroyed?
假设我有一个类
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构造函数。据我所知,move构造函数在两者之间交换字段指针,这样就不会发生复制。
所以我的问题来了。当a2
被实例化时,它在a2
自身内为字段some_obj_
分配内存。当移动发生时,我们交换指针,使a1
的some_obj_
现在指向a2
所持有的内存块(而不是在其自己的内存空间上复制它)。将来,当a2
超出范围时,例如,包含a2
的函数返回,因此堆栈帧被清理,因为a2.some_obj_
位于a2
中,所以它也被删除。既然a1.some_obj_
在移动后指向了a2
现在已经清理过的内存,那么a1
会丢失那部分信息吗?
似乎按照上面的逻辑,a1
现在将指向无效的内存空间。
以下是移动类的典型实现
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)的句柄)。对于其他普通数据,移动与复制没有什么不同。
如果move构造函数实现得当,就不会泄漏任何内存。特别是,典型的move构造函数将rhs指针设置为nullptr
,因此moved-from对象的析构函数中的后续delete
是no-op。超级简化示例:
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
}
相关文章:
- 关于std::move的使用,是否有编译警告
- 是否可以在 C++03 中定义'move-and-swap idiom'等效项
- '[](std::list& list)<int>{return std::move(list)}(list)' 是否保证将 'list' 留空?
- 是否有必要使用 std::move?这不是已经是一个右值参考了吗?
- 使用 std::move 将参数传递给函数,如果该参数声明为按值传递或使用移动操作数 &&,是否有区别?
- 编译器是否足够聪明,以至于 std::move 变量超出范围?
- 在构造函数中初始化成员时,是否应该在成员上使用 std::move?
- 在返回语句中构造对象时,std::move() 是否有助于或阻止 RVO?
- std::move 是否始终按预期工作
- 防御性地应用 std::move 到平凡可复制的类型是否不可取
- 如果对象在同一层次结构中,-Wreturn-std-move clang 警告是否正确
- 是否可以 std::move 局部堆栈变量?
- 移动变量是否有效,可以在 std::move 之后使用
- 使用 std::move 转储成员的设计是否可以接受?
- std::vector的move构造函数是否调用项的move构造器
- 是否可以将 std::move 对象移出函数?(C++11).
- std::move on std::string 是否保证 .c_str() 返回相同的结果
- 检查容器上是否完成了std::move
- std::basic_string是否正式具有隐式生成的move构造函数
- 当源obj被销毁时,使用move-cst是否会丢失内存