【问题标题】:How to avoid temporary object on the stack when using the allocator concept?使用分配器概念时如何避免堆栈上的临时对象?
【发布时间】:2011-11-04 13:28:52
【问题描述】:

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

分配器使用in-placement new来分离内存的分配和对象的构造。因此,可以获取大量元素并在真正需要对象时仅调用构造函数。

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

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

【问题讨论】:

    标签: c++ stl allocator


    【解决方案1】:

    你可以使用allocate_shared

    【讨论】:

    • 我正在使用 Linux,但我坚持使用 C++03
    • 然后使用std::tr1::allocate_shared,来自&lt;tr1/memory&gt;
    • 不幸的是,技术版本 1 不是 C++03 的一部分,而是 C++0x 的一部分,但感谢您的提示,如果编译器确实支持 C++11,我可能会添加实验性功能。
    • 或者boost::allocate_shared,因为问题是关于boost::shared_ptr
    • @Alex:不,不完全是。 in C++11 中没有 TR1,因为 C++11 实际上包含所有这些内容作为实际标准的一部分。相反,TR1 是一个用于 C++98/03 的库,它早于新标准,并且与流行的编译器一起发布了很长时间。
    猜你喜欢
    • 1970-01-01
    • 2019-05-12
    • 2021-12-25
    • 2013-12-31
    • 2013-01-25
    • 1970-01-01
    • 1970-01-01
    • 2014-04-17
    • 2012-07-19
    相关资源
    最近更新 更多