Search code examples
c++pointersvectorallocator

Can i forbid vector to reallocate objects?


Let's say we have a vector of double (values) and a vector containing objects that store pointers to the elements of the vector of 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());
    }
};

(objects after adding are never deleted)

It is known that when a vector reallocates objects, all pointers break. I can pre-call reserve(), but the problem is that I don't know how many objects will be stored, maybe 5, or maybe 500'000 and shrink_to_fit() will break pointers anyway.

I can use a deque in this case, but I'm wondering if I can prevent the vector from reallocating memory when I call shrink_to_fit (), or some other way?


Solution

  • The key is

    objects after adding are never deleted

    Rather than store pointers/iterators/references to elements of the vector, store a pointer1 to the vector and an index.

    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. pointer and not reference so we are a SemiRegular type (and can easily define == to be Regular)