【问题标题】:unique_ptr boost equivalent?unique_ptr 提升等效?
【发布时间】:2011-02-26 13:36:51
【问题描述】:

在 boost 库中是否有 C++1x 的 std::unique_ptr 的等效类?我正在寻找的行为是能够拥有一个异常安全的工厂函数,就像这样......

std::unique_ptr<Base> create_base()
{
    return std::unique_ptr<Base>(new Derived);
}

void some_other_function()
{
    std::unique_ptr<Base> b = create_base();

    // Do some stuff with b that may or may not throw an exception...

    // Now b is destructed automagically.
}

编辑:现在,我正在使用这个 hack,这似乎是目前我能得到的最好的......

Base* create_base()
{
    return new Derived;
}

void some_other_function()
{
    boost::scoped_ptr<Base> b = create_base();

    // Do some stuff with b that may or may not throw an exception...

    // Now b is deleted automagically.
}

【问题讨论】:

  • 另外,是否可以通过让复制构造函数具有移动语义,然后析构函数在释放前检查来创建这种效果?

标签: c++ boost c++11 unique-ptr


【解决方案1】:

如果没有 C++0x(它是标准库的一部分,因此 Boost 不需要提供它),就不可能创建像 unique_ptr 这样的东西。

特别是没有右值引用,这是 C++0x 中的一个特性,unique_ptr 的健壮实现是不可能的,不管有没有 Boost。

在 C++03 中,有一些可能的替代方案,尽管每个都有其缺陷。

  • 就功能而言,boost::shared_ptr 可能是最简单的替代品。你可以在任何你可以使用unique_ptr 的地方安全地使用它,并且它会起作用。由于增加了引用计数,它不会那么有效。但是,如果您正在寻找一个能够处理unique_ptr 可以做的所有事情的简单替代品,那么这可能是您最好的选择。 (当然,shared_ptr 也可以做更多事情,但它也可以简单地用作unique_ptr 的替代品。)
  • boost::scoped_ptrunique_ptr 类似,但不允许转让所有权。只要智能指针在其生命周期内保持独占所有权,它就可以很好地工作。
  • std::auto_ptr 的工作方式与unique_ptr 非常相似,但有一些限制,主要是它不能存储在标准库容器中。如果您只是在寻找一个允许所有权转移的指针,但它并不意味着存储在容器中或复制,那么这可能是一个不错的选择。

【讨论】:

  • +1 for auto_ptr - 因为 unique_ptr 不会在 places that auto_ptr causes bugs 中编译,这正是 OP 正在寻找的。​​span>
  • Howard Hinnant 针对 c++03 的 unique_ptr 工作得很好,因为不存在 r 值引用。
  • boost::scoped_ptr 是一个糟糕的选择,因为它不适用于前向声明的类。 boost::shared_ptr 是一个糟糕的选择,因为它的开销很大。
  • boost::scoped_ptr 的另一个缺点是它不提供客户删除器。
  • 到目前为止,这个答案不再无效。请参阅 my answer,它描述了 Boost 1.57 中引入的 boost::movelib::unique_ptr
【解决方案2】:

Boost 1.57 开始,Boost.Move 库中有一个官方的unique_ptr 实现。

来自documentation

(...) std::unique_ptr 的直接替代品,也可用于 C++03 编译器。

代码在&lt;boost/move/unique_ptr.hpp&gt; 头文件中可用,并且位于boost::movelib 命名空间中。此外,Boost.Move 库在&lt;boost/move/make_unique.hpp&gt;boost::movelib 命名空间中提供了make_unique() 工厂函数。

因此问题中的示例可以这样实现:

#include <boost/move/unique_ptr.hpp>

using boost::movelib::unique_ptr;

unique_ptr<Base> create_base()
{
    return unique_ptr<Base>(new Derived);
}

a live example on Wandbox。请注意,代码可以在 C++98 模式下使用 gcc 4.6.4 正常编译 (!)。

boost::movelib::unique_ptr 的有趣之处在于,当您将其应用于基类/派生类的情况时,该实现为基类中虚拟析构函数的声明提供了编译时检查。如果您碰巧省略了它the code won't compile(单击“运行(...)”按钮以查看编译器错误消息)。

一个小问题是包含来自boost/move 目录但代码位于boost::movelib 命名空间中(细微差别但可能很烦人)。

更多详情请参见a thread on boost mailing list

感谢 Ion Gaztañaga 提供这段绝对独特且有用的代码。

【讨论】:

    【解决方案3】:

    您可能想尝试 Howard Hinnant 的“概念证明”unique_ptr&lt;&gt; C++03 实现(免责声明 - 我没有):

    他的一个例子是返回unique_ptr&lt;int&gt;

    unique_ptr<int> factory(int i)
    {
        return unique_ptr<int>(new int(i));
    }
    

    【讨论】:

    • 我在生产代码中使用过这个,效果很好。我们遇到的唯一问题是调用boost::make_shared,以获取带有unique_ptr 参数的class
    【解决方案4】:

    interprocess 库中的unique_ptr 怎么样?

    【讨论】:

    • 可以安全地从函数返回吗?我对此一无所知(但也许我只是瞎了眼)。此外,考虑到它在进程间库而不是智能指针库中,它是否“正确”使用?
    • @wowus:不。这依赖于 C++0x 中新增的移动语义。这不能简单地通过 boost 来模拟——该功能必须存在于编译器本身中。
    • 刚看了,它需要右值引用。因此,不是我要找的。​​span>
    • Interprocess unique_ptr 有自己的 C++03 移动仿真,如果我没记错的话,它与 Boost.Move 相同。
    • @Clark Gaebel,正如文森特在上面的评论中指出的那样,是的,来自 Boost.Interprocess 的 unique_ptr 可以通过boost::move() 从函数安全地返回。两年来,我一直在使用 Boost.Interprocess 的 unique_ptr,并取得了很大的成功。
    【解决方案5】:

    我使用了 Howard Hinnant 的 unique_ptr。如果您不擅长从编译器中读取疯狂的元编程错误,您可能需要避开。然而,在 90% 的情况下,它的行为就像一个 unique_ptr。

    否则我建议将参数传递为boost::scoped_ptr&amp; 并在内部交换以窃取所有权。要获取 unique_ptr 样式的返回值,请使用 auto_ptr。在shared_ptrscoped_ptr 中捕获auto_ptr 返回值,以避免直接使用auto_ptr

    【讨论】:

      猜你喜欢
      • 2010-12-02
      • 1970-01-01
      • 2012-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多