c++stdvectorplacement-new

Std::vector vs. placement new for communicating const array with size known at run-time


I have two methods for creating a list of objects at run-time which have potential downsides that I'd like to consider. Ultimately I am wondering which one more e

The criteria of my problem:

My understanding:

Does this reasoning align with the intention of placement new or am I missing a more appropriate standard container?

In the example below object list option 1 & 2 represent a std::vector based approach vs. placement new respectively. For simplicity I left out any exception handling. The ideal downstream usage (e.g. no resize) looks the same to me (access via [] operator).

For reference std::vector::emplace vs placement new might seem like a relevant question but I am trying to find an ideal solution for this particular set of criteria where the other question is considerably more vague. It is also possible that a different container or pattern would better solve this and that the two options here are simply a starting point.

#include <vector>

class minorObj{
    const int value;
    public:
    minorObj() = delete;
    minorObj(int x):value(x){}
};



class majorObj{
    const int N;
    public:
    std::vector<minorObj> objList_op1;
    minorObj*            objList_op2;
    majorObj(int size):N(size){
        objList_op1.reserve(N);
        objList_op2 = static_cast<minorObj*>(operator new[](N * sizeof(minorObj)));
        for(int i = 0; i<N;i++){
            objList_op1.emplace_back(minorObj(i));
            new(&objList_op2[i]) minorObj(i);
        }
    }
    ~majorObj(){
        for(int i = N -1; i >= 0; i--){
            objList_op2[i].~minorObj();
        }
    }
};

void someFn(){majorObj(25);} //added some different scope to emphasize need for proper memory mgmt

int main(){
    someFn();
    return 0;
}

Solution

  • Based on Quentin's comment above an example implementation of a wrapper class could be done with the following template class. This allows for run-time initialization benefits of std::vector while allowing/disallowing other operations as needed. Access to the objects it contains would be the same via the subscript operator.

    template <class T>
    class RuntimeArray{
        private:
        std::vector<T> values;
        public:
        RuntimeArray() = delete;
        RuntimeArray(const std::vector<int>& inputs){ // can be whatever type to initialize
            values.reserve(inputs.size());
            for(int i = 0; i < inputs.size(); i++){
                values.emplace_back(inputs[i]);
            }
        }
        T& operator [](int i){
            return values[i];   
        }
        const T& operator[](int i) const{
            return values[i];
        }
        // std::vector without std::vector::push_back or std::vector::erase etc.
    };