如何对带有句柄的类使用std :: vector

时间:2019-05-22 09:29:34

标签: c++ c++11 vector move-constructor

我定义了以下类,女巫创建并释放了不透明的对象(例如,操作系统句柄)

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,以便在删除旧对象时新创建的对象不会变得无效?

1 个答案:

答案 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作为无效值。