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

Popular posts from this blog

powershell Start-Process exit code -1073741502 when used with Credential from a windows service environment -

twig - Using Twigbridge in a Laravel 5.1 Package -

c# - LINQ join Entities from HashSet's, Join vs Dictionary vs HashSet performance -