如何使用 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作为无效值。