我可以禁止向量重新分配对象吗?

问题描述

假设我们有一个double(值)向量和一个包含对象的向量,这些对象存储了指向double(vars)向量元素的指针:

class Var
{
public:
    explicit Var(double* v) : _value(v) {};
    ~Var() {};

    const double get() const { return *_value; };
    void set(const double v) { *_value = v; };

private:
    double* _value;
};


struct Vars
{
    Vars()
    {
        //values.reserve(1000'000);
    }
    vector<double> values{};
    vector<Var> vars{};

    void push(const double v)
    {
        values.push_back(v);
        vars.emplace_back(&values.back());
    }
};

添加后的对象永远不会删除

众所周知,当向量重新分配对象时,所有指针都会中断。 我可以预调用reserve(),但是问题是我不知道将存储多少个对象,也许是5个,或者可能是500'000个,而shrink_to_fit()仍然会破坏指针。

在这种情况下,我可以使用双端队列,但是我想知道是否可以在调用shrink_to_fit()或其他方法时阻止向量重新分配内存?

解决方法

std::vector不允许您在保留其余部分的同时将其部分缓冲区返回堆。 std::allocator“概念”中没有API可以做到这一点。

std::vector保证连续存储,因此不能分段分配。

如果不需要连续存储,请使用std::deque或手动复制的副本(双端队列使一些性能关键参数可以自由选择以供实现选择,并且不会暴露将它们配置为结束的能力-用户;因此,如果您的双端队列不适合您的用例,则可能必须自己滚动。)

std::deque是一个固定大小的缓冲区的动态数组,外加少量的终端管理状态。它允许使用动态大小的容器和O(1)随机访问进行稳定的存储,并且容器开销仅占存储量的一小部分(缩放开销是每个块的指针,并且块大小比指针大很多倍)在我所见过的每一种实现上)。

与vector相比,缺点是存储不连续,并且iterator / []查找具有间接的额外指针,但这将是一个奇怪的连续存储容器,可以满足您的其他需求

,

关键是

添加后的对象永不删除

而不是存储指向向量元素的指针/迭代器/引用,而是存储指向向量的指针 1 和索引。

class Var
{
public:
    explicit Var(std::vector<double> * vec,size_t index) 
      : vec(vec),index(index) {};

    double get() const { return vec->at(index); };
    void set(double v) { vec->at(index) = v; };

private:
    std::vector<double> * vec;
    size_t index;
};


struct Vars
{
    vector<double> values;
    vector<Var> vars;

    void push(double v)
    {
        vars.emplace_back(&values,values.size());
        values.push_back(v);
    }
};
  1. 指针而不是引用,因此我们是SemiRegular类型(并且可以轻松地将==定义为 Regular
,

我可以禁止向量重新分配对象吗?

您可以通过不执行会使向量(可能)重新分配的操作来避免重新分配。

除了使向量为const外,没有其他方法可以阻止执行这些操作。一种解决方案是将向量设置为私有成员(并且永远不要返回指向该成员的非常量指针/引用),在这种情况下,您只需要担心成员函数不会执行这些操作即可。

问题是我不知道要存储多少个对象,也许是5个,也许是50万个

如果在插入之间不需要指针,则可以一次执行所有插入(无论插入多少),然后再获取指针,然后不再修改向量。

在其中以上是不是一种选择,如果需要的指针保持有效的一般情况下,载体是不数据结构的一个合适的选择。列表或双端队列将取决于您如何使用容器。

关于示例:拥有对象向量和指向这些对象的(包含包装器的)指针向量似乎毫无意义。