Как избежать временного объекта в стеке при использовании концепции распределителя? - PullRequest
2 голосов
/ 04 ноября 2011

Следующий код пытается создать узлы двоичного дерева и вернуть ему boost :: shared_ptr ().

void create_node(shared_ptr &in,
            unsigned var_name,
            shared_ptr left=shared_ptr(),
            shared_ptr right=shared_ptr()) {
  typename nodes::pointer p = A.allocate(1);
  // a temporary node element is created on the stack here.
  A.construct(p, (node(var_name, left, right)));
  in = shared_ptr(p);
}

Рассматривая код libstdc ++, я обнаружил, что вызываемые мной функции std :: allocator выглядят так:

pointer
allocate(size_type __n, const void* = 0)
{ 
  if (__n > this->max_size())
    std::__throw_bad_alloc();
  return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
}

void 
construct(pointer __p, const _Tp& __val) 
{ ::new((void *)__p) _Tp(__val); }

Распределитель использует новое размещение для разделения выделения памяти и построения объекта. Таким образом, можно получить большое количество элементов и вызывать только конструктор, когда объект действительно необходим.

Функция create_node создает отдельный объект с использованием концепции распределителя и использует shared_ptr для вызова деструктора при необходимости. Чтобы сделать эти одиночные распределения дешевыми, я хочу заменить распределитель позже (следовательно, я хочу распределитель, который использует распределение пула).

Когда я вызываю эту функцию, она создает временный экземпляр в стеке, а затем копирует элементы узла в местоположение кучи. Как я могу заставить компилятор немедленно создать объект на месте? Таким образом, я хочу перевернутую оптимизацию именованных возвращаемых значений (NRVO). Это возможно?

1 Ответ

3 голосов
/ 04 ноября 2011

Вы можете использовать allocate_shared.

...