Reputation: 100
I need to populate a std::vector with dynamically instantiated objects.
class MyClass {
std::vector<MyObject*> m_objects;
//...
}
This is the use case I need with naive code:
void MyClass::MyFunc1(std::vector<MyType> data)
{
for (auto&& d : data)
m_objects.push_back(new MyObject(d));
}
So I take an array of n data elements in parameter, and construct n objects using these data elements. I put all elements in the vector.
I would like to find some fast way to do it, mostly by avoiding doing lot of new and lot of calls to push_back. I ended with the following solution, dividing execution time by a factor of two:
void MyClass::MyFunc2(std::vector<MyType> data)
{
size_t size = data.size();
MyObject *array = new MyObject[size];
MyObject **parray = new MyObject*[size];
for (int i = 0; i < size; i++)
parray[i] = &array[i];
m_objects.insert(m_objects.end(), &parray[0], &parray[size]);
for (int i = 0; i < size; i++)
m_objects[i]->data = data[i];
}
So I create all objects at once, and put them all at once using insert. One overhead is the creation of the array of pointers in order to be able to insert pointers on the objects instead of copying objects into the vector. Another is the need to manually construct the object afterward.
I am open to better solution, including using an other structure than a vector. Thank you!
Upvotes: 0
Views: 183
Reputation: 26292
A simple suggestion is to store objects in the vector, not pointers, and use reserve()
to preallocate space:
std::vector<MyObject> m_objects;
void MyFunc1(std::vector<MyType> data)
{
m_objects.reserve(m_objects.size() + data.size());
for (auto&& d : data)
m_objects.emplace_back(d);
}
If you need pointers, use smart pointers and reserve
:
std::vector<std::unique_ptr<MyObject>> m_objects;
void MyFunc1(std::vector<MyType> data)
{
m_objects.reserve(m_objects.size() + data.size());
for (auto&& d : data)
m_objects.push_back(std::make_unique<MyObject>(d));
}
Upvotes: 3