18

我们几乎已经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最终会在下一个标准中被标记为折旧,所以我想知道我可以用什么/如何替换这个实现

另外,还有什么其他原因可以让您考虑使用 anauto_ptr而不是 ashared_ptr吗?您是否看到将来迁移到 shared_ptr 有任何问题?


编辑:

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

3 回答 3

36

auto_ptrshared_ptr解决完全不同的问题。一个不会取代另一个。

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

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

于 2009-08-04T13:06:11.057 回答
14

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

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

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

另外,还有什么其他原因可以让您考虑使用 anauto_ptr而不是 ashared_ptr吗?您是否看到shared_ptr将来会出现任何问题?

就个人而言,我不会使用auto_ptr. 复制时删除太不直观了。 赫伯萨特似乎同意了。切换到scoped_ptrunique_ptrshared_ptr应该没有问题。具体来说,shared_ptr如果您不关心引用计数开销,则应该是直接替换。 scoped_ptr如果您不使用auto_ptr的所有权转移功能,则可以直接替换。如果您正在使用所有权转让,那么unique_ptr几乎是一个直接替代品,除了您需要明确调用move来转移所有权。有关示例,请参见此处。

于 2009-08-04T13:33:56.457 回答
1

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

于 2009-08-04T13:01:57.550 回答