为什么boost没有make_scoped()?

时间:2012-07-05 02:46:46

标签: c++ boost make-shared scoped-ptr

Boost的make_shared()函数在尝试创建shared_ptr时承诺异常安全。

为什么没有等效的make_scoped()?有没有共同的最佳做法?

以下是来自boost::scoped_ptr documentation的代码示例,对我来说似乎不安全:

    boost::scoped_ptr<Shoe> x(new Shoe);

这行代码将按顺序执行以下三项

  • Shoe
  • 分配堆内存
  • 调用Shoe
  • 的构造函数
  • 调用boost::scoped_ptr<Shoe>
  • 的构造函数

如果Shoe的构造函数抛出异常,内存将被泄露。 (参见R. Martinho Fernandes回答) scoped_ptr赢了处理释放因为它尚未构建。

这是疏忽吗?或者有没有我没注意到的解决方案?

3 个答案:

答案 0 :(得分:15)

scoped_ptr早于移动语义,并且在设计上是不可复制的。因此,make_scoped将无法实现,因为为了从函数返回对象,其类型必须是可移动的或可复制的。

答案 1 :(得分:14)

如果构造函数失败,则不会泄漏内存。这是new语义的一部分,没有涉及智能指针:

struct Foo { Foo() { throw 23; } };
new Foo(); // no memory leaked

make_shared提供的额外异常安全性来自于您在表达式中初始化两个shared_ptr并且两个初始化未按顺序排序,就像这样在函数调用参数中:

struct Bar {
    Bar(bool fail) {
        if(fail) throw 17;
    }
}
f(shared_ptr<Bar>(new Bar(true)), shared_ptr<Bar>(new Bar(false)));

由于new Bar(true)shared_ptr<Bar>(new Bar(true))new Bar(false)shared_ptr<Bar>(new Bar(false))的评估之间没有排序,因此可能会发生以下情况:

    评估
  1. new Bar(false)并成功:分配内存;
  2. new Bar(true)被评估并失败:它不会泄漏由此评估产生的内存;
  3. 目前尚未构建shared_ptr,因此#1中分配的内存现已泄露。

答案 2 :(得分:1)

如果Shoe抛出,那么Shoe没有构造,因此没有任何scoped_ptr可以真正做到。没有? scoped_ptr x在堆栈上,将在范围退出时清理。