标准::交换中不需要的析构函数调用
Unwanted destructor call in std::swap
我遇到了std::swap的问题。 我必须交换一个对象。 该对象在其析构函数中释放内存。 我编写了一个移动构造函数和一个移动赋值运算符,用于将指针复制到该内存。 默认构造函数将该指针设置为 NULL。
当然,我有一个常规的复制构造函数和赋值运算符,但它们分配和复制内存,这显然不是我想要的交换操作。
当我调用 std::swap 时,它会使用我的移动构造函数从_Left创建一个临时对象。 然后,它使用我的移动赋值运算符将_Right移动到_Left,最后,它将临时对象移动到_Right。
当你到达std::swap的底部时,这一切看起来都很好。 但是,当您走出它的底部时,临时对象的析构函数将运行,从而释放_Right对象预期具有的内存。
通常接受的方法是什么? 我希望避免编写交换函数,因为这是移动构造函数/移动赋值运算符的重点。 我必须使用自己的 swap() 来避免这种情况吗?
移动操作应使要移动的对象处于可破坏状态,该状态可能与移动状态不同。
如果我理解正确,听起来您的对象的 move-ctor 需要将要移动的对象中的指针设置为它们附带的值以外的其他内容。这些现在移动的对象上的后续 dtor 应该单独保留它们曾经引用的内存。
好的,经过更多的研究,我明白了我的基本问题和解决方案。
简短版本:
在移动构造函数中,从源对象复制值,然后将它们设置为默认构造函数运行时的值。
长版本:
创建移动构造函数或移动赋值运算符时,必须将要从中分配的对象保留为可销毁的默认状态。 交换无法实现此目的。 相反,您需要首先从源对象窃取资源,然后将源对象的成员设置为构造函数运行时它们所处的状态。
交换让你陷入热水的一个例子是你正在处理指针的地方,就像我一样。 您无法复制或交换它。 如果复制指针,则指针值在被销毁时仍将位于源对象中。 如果交换指针,则它将是一个未初始化的值,这可能会使析构函数崩溃。相反,应复制指针值,然后将源对象中的指针设置为 NULL。 当然,释放内存时必须在析构函数中检查 NULL。
如果你窃取的成员之一是你控制的类实例,那么你应该使用 std::move 来复制它,因为这将调用它的移动赋值运算符,也使它可破坏。
奖金:
不要重新发明轮子。 只需从移动构造函数调用移动赋值运算符即可。
void CObject::CObject(CObject&& other)
{
*this = std::move(other);
}
CObject& CObject::operator = (CObject&& other)
{
// m_pResource is a pointer.
// Copy the value.
m_pResource = other.m_pResource;
// Set other to default state so the destructor doesn't free it.
other.m_pResource = NULL;
// m_iCount is an int who's value does not matter in the destructor.
m_iCount = other.m_iCount;
// m_Obj is a class instance.
// Invoking move semantics will use its move assignment operator if it has one.
m_Obj = std::move(other.m_Obj);
return *this;
}
- 析构函数调用
- 在具有向量的类构造函数中进行析构函数调用
- 从 c++ 中派生类的析构函数调用虚函数
- C++析构函数调用两次,堆栈分配的复合对象
- C++ 在析构函数调用之前删除的动态成员数组
- 析构函数调用c++中的一个向量
- Singleton模式中的手动析构函数调用:调用多次
- 从内部类的析构函数调用虚拟函数
- 与 boost odeint 集成期间的析构函数调用
- 堆栈展开如何与析构函数调用有关?
- C++:优化析构函数调用
- 以逗号分隔的表达式中的析构函数调用
- GCC 9.1 返回 void& 作为显式析构函数调用的结果类型。这是一个错误吗?
- 从C++中的虚拟析构函数调用虚拟方法
- 从指针返回对象时出现意外的析构函数调用
- 使用 decltype 显式析构函数调用
- C++析构函数调用了错误的对象
- 了解虚拟函数和析构函数调用
- 多重继承析构函数调用他自己和父析构函数?c++
- 析构函数调用表单不适当的库