15

Boost 的make_shared()函数在尝试创建shared_ptr.

为什么没有make_scoped()等价物?有共同的最佳实践吗?

boost::scoped_ptr这是文档中对我来说似乎不安全的代码示例:

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

这行代码将按顺序完成这三件事:

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

如果 for 的构造函数Shoe抛出异常, 就会导致内存泄漏。 (请参阅 R. Martinho Fernandes 的回答)scoped_ptr不会处理释放,因为它尚未构建。

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

4

3 回答 3

15

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

于 2012-07-05T03:00:28.083 回答
14

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

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

make_shared当你shared_ptr在一个表达式中初始化两个 s 并且这两个初始化不是 sequenced时,提供了额外的异常安全性,就像函数调用参数中的情况一样:

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)被评估并失败:它不会泄漏由此评估产生的内存;

此时构造了No shared_ptr,因此在 #1 中分配的内存现在泄漏了。

于 2012-07-05T02:57:18.343 回答
1

如果 Shoe 抛出,则 Shoe 没有被构造,因此 scoped_ptr 无能为力。不?scoped_ptr x 在堆栈上,将在范围退出时被清理。

于 2012-07-05T02:56:48.847 回答