c++11 - How to efficiently allocate space for vector of pointers to virtual base class in modern C++ -
i have following data model
struct base { int x_; int y_; int z_; virtual int getid() const; virtual int getvalue() const = 0; virtual base* create() const = 0; bool operator<(const base &other); }; struct derived0 : public base { virtual derived0* create() const { return new derived0(); }; virtual int getid() const; virtual int getvalue() const; }; //... struct derivedn : public base { virtual derivedn* create() const { return new derivedn(); }; virtual int getid() const; virtual int getvalue() const; };
and fill in following way (simplified)
int n = 0; std::shared_ptr<base> templ[100]; templ[n++] = std::make_shared<derived0>(); //... templ[n++] = std::make_shared<derivedn>(); std::vector<std::shared_ptr<base>> b; (int = 0; < n; i++) { while (...) { // hundreds of thousands iterations std::shared_ptr<base> ptr(templ[i]->create()); // previous call consumes of time //... b.push_back(ptr); } } std::sort(b.begin(), b.end()); // ...
since need huge amount of derived objects wonder if initialization can done more efficiently. in showed case of time spend creating single shared pointers.
i tried way preallocating array of base
objects (since derived
have same size), casting virtual type each template , storing raw pointers array. not surprisingly such approach many times faster. not clean, vector
cannot used , memory management problematic.
can give me advice, how efficiently in c++ way
- if objects have same size?
- if size varies?
it seems me lot of performance issues solved using std::unique_ptr
, reserving std::vector
memory in advance.
std::shared_ptr<base> ptr(templ[i]->create());
the above line involves dynamically allocating memory both derived type , std::shared_ptr
control block. if don't have shared ownership semantics, using std::unique_ptr
instead eliminate need 1 of allocations.
b.push_back(ptr);
when above enough times, vector run out of memory has allocated , try , allocate more. std::vector
designed in such way has amortized constant time complexity, can mitigate that, huge vectors, save time.
your new code might like:
std::vector<std::unique_ptr<base>> b; b.reserve(n * /*number of iterations*/); (int = 0; < n; i++) { while (...) { // hundreds of thousands iterations std::unique_ptr<base> ptr(templ[i]->create()); //... b.push_back(ptr); } }
as aside, limit code duplication prototype array creation doing this:
template <class base, class... derived, std::size_t... idx> auto arrayofuniquederived (std::index_sequence<idx...>) { std::array<std::unique_ptr<base>, sizeof...(derived)> arr; (void) std::initializer_list<int> { (arr[idx] = std::make_unique<derived>(), 0)... }; return arr; } template <class base, class... derived> auto arrayofuniquederived () { return arrayofuniquederived<base,derived...>(std::index_sequence_for<derived...>{}); }
then use like:
std::array<std::unique_ptr<base>,3> templ = arrayofuniquederived<base,derived0,derived1,derived2>();
Comments
Post a Comment