使用分配器概念时如何避免堆栈上的临时对象?

时间:2011-11-04 13:28:53

标签: c++ stl allocator

以下代码尝试创建二叉树的节点并向其返回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); }

allocator使用in-placement new来分隔内存的分配和对象的构造。因此,当真正需要一个对象时,可以获得大量元素并仅调用构造函数。

create_node函数通过使用allocator概念创建单个对象,并在需要时使用shared_ptr调用析构函数。为了使这些单个分配便宜,我想稍后替换分配器(因此我想要一个使用池分配的分配器)。

当我调用此函数时,它将在堆栈上创建一个临时实例,然后将节点的元素复制到堆位置。如何强制编译器立即创建对象?因此,我想要一个倒置的命名返回值优化(NRVO)。这可能吗?

1 个答案:

答案 0 :(得分:3)

您可以使用allocate_shared