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;
}
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.
};