我定义了以下类,女巫创建并释放了不透明的对象(例如,操作系统句柄)
class A
{
public:
A(...)
{
allocateHandle(&h);
}
~A()
{
freeHandle(h);
}
SomeHandle h;
}
创建和调整A的std :: vector的大小时,程序崩溃。
std::vector<A> vec;
vec.reserve(2);
vec.emplace_back(...);
vec.emplace_back(...);
vec.emplace_back(...); //crash
std :: vector重新分配内存时,它会在所有对象上调用move构造函数,因此也会在A中移动句柄(基本上是整数)。
但是,它还会在旧对象上调用析构函数,并调用freeHandle()
,从而释放了新对象仍然具有的句柄后面的内存,该内存变得无效并导致崩溃。
我应该如何实现move-constructor,以便在删除旧对象时新创建的对象不会变得无效?
答案 0 :(得分:8)
您需要向对象添加一些“未持有有效的句柄”状态。如果您的SomeHandle
已经具有“无效的句柄”值(通常,通常使用0表示该值),则可以使用该值:
class A
{
public:
A(...)
{
allocateHandle(&h);
}
A(A &&src) : h(src.h)
{
src.h = INVALID;
}
A& operator= (A &&rhs)
{
if (this == &rhs) return *this;
if (h != INVALID) freeHandle(h);
h = rhs.h;
rhs.h = INVALID;
return *this;
}
~A()
{
if (h != INVALID)
freeHandle(h);
}
SomeHandle h;
}
如果没有“无效的句柄”值,则可以将h
的类型更改为std::optional<SomeHandle>
,并使用std::nullopt
作为无效值。