【问题标题】:When would you use an std::auto_ptr instead of boost::shared_ptr?你什么时候会使用 std::auto_ptr 而不是 boost::shared_ptr?
【发布时间】:2010-11-16 16:14:01
【问题描述】:

我们几乎已经在所有代码中转而使用boost::shared_ptr,但是我们仍然有一些使用std::auto_ptr 的孤立案例,包括单例类:

template < typename TYPE >
class SharedSingleton
{
public: 
    static TYPE& Instance()
    {
        if (_ptrInstance.get() == NULL)
            _ptrInstance.reset(new TYPE);
        return *_ptrInstance;
    }

protected: 
    SharedSingleton() {};

private:
    static std::auto_ptr < TYPE > _ptrInstance;
};

有人告诉我,没有将其设为shared_ptr 是有充分理由的,但我这辈子不明白为什么?我知道auto_ptr 最终会在下一个标准中被标记为已弃用,所以我想知道我可以用什么/如何替换这个实现

另外,还有什么其他原因可以让您考虑使用auto_ptr 而不是shared_ptr您认为将来迁移到 shared_ptr 有什么问题吗?


编辑:

  1. 因此,在回答“我可以在上面的代码中安全地将 auto_ptr 替换为 shared_ptr 吗”时,答案是肯定的 - 但是我的性能会受到一点影响。
  2. auto_ptr 最终被标记为折旧并且我们转移到std::shared_ptr 时,我们需要彻底测试我们的代码以确保我们遵守不同的所有权语义。

【问题讨论】:

  • auto_ptr 正在被替换,主要是因为它处理移动语义的方式,因为在这种情况下,保持向后兼容性比更新它更干净。不过,新类应该*crosses finger*几乎是一个替代品。

标签: c++ stl boost shared-ptr auto-ptr


【解决方案1】:

auto_ptrshared_ptr 解决完全不同的问题。一个不能替代另一个。

auto_ptr 是实现RAII 语义的指针的薄包装,因此即使遇到异常,资源也总是被释放。 auto_ptr 根本不执行任何引用计数或类似操作,它在创建副本时不会使多个指针指向同一个对象。事实上,这是非常不同的。 auto_ptr 是赋值运算符修改 source 对象的少数类之一。考虑一下auto_ptr wikipedia page的这个无耻插件:

int *i = new int;
auto_ptr<int> x(i);
auto_ptr<int> y;

y = x;

cout << x.get() << endl; // Print NULL
cout << y.get() << endl; // Print non-NULL address i

注意如何执行

y = x;

不仅修改 y,还修改 x。

boost::shared_ptr 模板可以轻松处理指向同一个对象的多个指针,并且该对象仅在对它的最后一个引用超出范围后才会被删除。此功能在您的场景中没有用,它(尝试)实现Singleton。在您的场景中,总是有 0 引用到 1 引用到类的唯一对象,如果有的话。

本质上,auto_ptr 对象和shared_ptr 对象具有完全不同的语义(这就是为什么你不能在容器中使用前者,但对后者这样做很好),我当然希望你有很好的测试来捕捉您在移植代码时引入的任何回归。 :-}

【讨论】:

    【解决方案2】:

    其他人已经回答了为什么此代码使用auto_ptr 而不是shared_ptr。解决您的其他问题:

    我可以用什么/如何替换这个实现?

    使用boost::scoped_ptrunique_ptr(在Boost 和新的C++ 标准中都可用)。 scoped_ptrunique_ptr 都提供严格的所有权(并且没有引用计数开销),并且它们避免了 auto_ptr 令人惊讶的删除复制语义。

    另外,还有什么其他原因让您考虑使用auto_ptr 而不是shared_ptr?并且您认为将来转移到shared_ptr 有什么问题吗?

    就个人而言,我不会使用auto_ptr。复制时删除太不直观了。 Herb Sutter seems to agree。切换到scoped_ptrunique_ptrshared_ptr 应该没有问题。具体来说,如果您不关心引用计数开销,shared_ptr 应该是一个替代品。如果您不使用auto_ptr 的所有权转移功能,scoped_ptr 是一个替代品。如果您使用的是所有权转让,那么unique_ptr 几乎是一个直接替代品,只是您需要改为显式调用move 来转让所有权。示例见here

    【讨论】:

      【解决方案3】:

      auto_ptr 是我使用的唯一一种智能指针。我使用它是因为我不使用 Boost,并且因为我通常更喜欢我的面向业务/应用程序的类而不是显式 定义删除语义和顺序,而不是依赖于 智能指针的集合或单个智能指针。

      【讨论】:

      • 智能指针是用 C++ 编写安全高效代码的有用工具。没有它们,很难编写异常中立、无内存泄漏的程序。
      • auto_ptr(我已经说过我使用)是一个智能指针!
      • 好吧 auto_ptr 不是那么聪明 ;-) 你不能用它来处理共享资源。因此,您可能已经编写或应该拥有自己的 ref 计数指针,而这正是 shared_ptr 为您所做的。我发现不使用除 auto_ptr 之外的任何智能指针是非常糟糕的建议。我的建议正好相反,因为 auto_ptr 被赋予了两个职责:确保无论我们如何离开作用域都正确销毁它,以及将对象从一个位置安全地转移到另一个位置。应改为使用 shared_ptr 或 unique_ptr。
      • 我不相信共享资源。一个资源应该属于一个类的一个实例。而且我没有建议不要使用任何其他类型的智能指针 - 我描述了我的工作。
      • 那么横切关注点、上下文对象、共享数据、优化策略、硬件接口...... - 描述你所做的事情和提供建议的方式不同:S
      猜你喜欢
      • 2015-04-04
      • 2010-09-23
      • 2010-09-23
      • 2020-01-10
      • 2011-06-23
      • 2010-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多