如何使用 std::vector for 类 with handles
How to use std::vector for classes with handles
我已经定义了以下 class 创建并释放了一个不透明的对象(例如操作系统句柄)
class A
{
public:
A(...)
{
allocateHandle(&h);
}
~A()
{
freeHandle(h);
}
SomeHandle h;
}
创建和调整 std::vector 的 A 时,程序崩溃。
std::vector<A> vec;
vec.reserve(2);
vec.emplace_back(...);
vec.emplace_back(...);
vec.emplace_back(...); //crash
当std::vector重新分配内存时,它会调用所有对象的移动构造函数,因此也会移动 A 中的句柄(基本上是一个整数)。
然而,它也调用了旧对象的析构函数,旧对象调用了freeHandle()
,因此它释放了句柄后面的内存,新对象仍然有,它变得无效并导致崩溃。
我应该如何实现移动构造函数,以便在删除旧对象时新创建的对象不会失效?
您需要为对象添加一些 "no valid handle held" 状态。如果您的 SomeHandle
已经有一个 "invalid handle" 值(通常使用 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;
}
如果没有"invalid handle"值,可以将h
的类型改为std::optional<SomeHandle>
,并使用std::nullopt
作为无效值。
我已经定义了以下 class 创建并释放了一个不透明的对象(例如操作系统句柄)
class A
{
public:
A(...)
{
allocateHandle(&h);
}
~A()
{
freeHandle(h);
}
SomeHandle h;
}
创建和调整 std::vector 的 A 时,程序崩溃。
std::vector<A> vec;
vec.reserve(2);
vec.emplace_back(...);
vec.emplace_back(...);
vec.emplace_back(...); //crash
当std::vector重新分配内存时,它会调用所有对象的移动构造函数,因此也会移动 A 中的句柄(基本上是一个整数)。
然而,它也调用了旧对象的析构函数,旧对象调用了freeHandle()
,因此它释放了句柄后面的内存,新对象仍然有,它变得无效并导致崩溃。
我应该如何实现移动构造函数,以便在删除旧对象时新创建的对象不会失效?
您需要为对象添加一些 "no valid handle held" 状态。如果您的 SomeHandle
已经有一个 "invalid handle" 值(通常使用 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;
}
如果没有"invalid handle"值,可以将h
的类型改为std::optional<SomeHandle>
,并使用std::nullopt
作为无效值。