【问题标题】:safe std::tr1::shared_ptr usage安全的 std::tr1::shared_ptr 使用
【发布时间】:2011-08-01 00:43:44
【问题描述】:

这种方法不安全吗?

#include <tr1/memory>

Foo * createFoo()
{
  return new Foo(5);
}

int main()
{
  std::tr1::shared_ptr<Foo> bar(create());

  return 0;
}

还是让createFoo 返回一个shared_ptr&lt;Foo&gt; 对象会更好?

【问题讨论】:

    标签: c++ memory-leaks shared-ptr exception-safe


    【解决方案1】:

    这个例子是安全的:如果shared_ptr 构造函数抛出一个异常,它delete 在抛出之前是它的指针参数(标准草案,20.9.11.2.1)。

    create 是否应该返回 shared_ptr 取决于它的客户可能合理地想要对其结果做什么。如果他们所做的只是将其包裹在 shared_ptr 中,则将其退回以增加安全性。 (是的,shared_ptr 可能会引入一些耦合。)

    【讨论】:

      【解决方案2】:

      您的示例按照您编写的方式是安全的。但是,您可以通过让您的工厂方法 createFoo() 返回一个自动指针而不是原始指针来使其更加防泄漏。这样你就可以保证不会有泄漏。

      所以你会得到:

      #include <memory>
      #include <tr1/memory>
      
      std::auto_ptr<Foo> createFoo()
      {
        return std::auto_ptr<Foo>(new Foo(5));
      }
      
      int main()
      {
        std::tr1::shared_ptr<Foo> bar(createFoo());
      
        return 0;
      }
      

      当然也可以让你的工厂方法返回一个 shared_ptr,但这可能被视为矫枉过正,因为返回的指针通常会很快超出范围,因为它将在赋值或构造函数中使用。此外,使用 auto_ptr 可以更清楚地说明指针的预期用途,当不熟悉您的代码的人必须理解它时,这始终是一个加分项。

      【讨论】:

      • 为什么更防漏?如果new Foo(5) 失败,它会破坏任何构造并释放内存。指针的返回不会失败,一旦它在shared_ptr 中就可以了。
      • 最好不要使用auto_ptr。在这种情况下,返回一个简单的指针就可以了。我同意大卫的观点。
      • 使用简单指针版本,可以做到Foo * p = createFoo(); p = createFoo();。如果您不总是将工厂方法返回的指针分配给智能指针,则可能会泄漏内存,使用 auto_ptr 解决方案,这是不可能的。
      • 鉴于 TR1 限制 (=no unique_ptr),我认为返回 std::auto_ptr 是件好事。如果需要,调用者可以.release() 指针,或者使用它来构造shared_ptr。如果 C++0x 的 unique_ptr 可用,我会更喜欢。 +1
      • @Darhuuk:我通常不担心这样的内存泄漏;一个小而简单的函数通常可以通过检查证明是正确的。如果它是一个更复杂的功能,我可能会选择auto_ptr。
      猜你喜欢
      • 2010-10-03
      • 1970-01-01
      • 1970-01-01
      • 2012-06-11
      • 1970-01-01
      • 2011-10-29
      • 1970-01-01
      • 2012-03-01
      • 1970-01-01
      相关资源
      最近更新 更多