你什么时候使用std :: auto_ptr而不是boost :: shared_ptr?

Ala*_*lan 17 c++ boost stl auto-ptr shared-ptr

我们已经转移到使用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;
};
Run Code Online (Sandbox Code Playgroud)

我被告知有一个很好的理由说明为什么没有这个shared_ptr,但对于我的生活,我不明白为什么?我知道auto_ptr最终会在下一个标准中被标记为折旧,所以我想知道我可以用什么/如何替换这个实现.

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


编辑:

  1. 所以,在回答"我能安全地更换auto_ptrshared_ptr在上面的代码",答案是肯定的-但我会带一个小的性能损失.
  2. auto_ptr最终标记为折旧并且我们转向时std::shared_ptr,我们需要彻底测试我们的代码以确保我们遵守不同的所有权语义.

Fre*_*abe 35

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
Run Code Online (Sandbox Code Playgroud)

注意如何执行

y = x;
Run Code Online (Sandbox Code Playgroud)

不仅修改y而且修改x.

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

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


Jos*_*ley 14

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

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

使用boost::scoped_ptr或者unique_ptr(在Boost和新的C++标准中都有).双方scoped_ptrunique_ptr提供严格的所有权(没有引用计数的开销),andthey避免令人惊讶的删除上拷贝语义auto_ptr.

另外,你有没有其他原因考虑使用auto_ptr而不是shared_ptr?你认为shared_ptr将来有什么问题吗?

就个人而言,我不会使用auto_ptr.复制删除太不直观了. Herb Sutter似乎同意.切换到scoped_ptr,unique_ptr或者shared_ptr应该没有问题.具体而言,shared_ptr如果您不关心引用计数开销,应该是替代品. scoped_ptr如果您不使用auto_ptr所有权转让功能,则可以直接替换.如果您使用的是所有权转让,那么unique_ptr除了您需要明确调用move转移所有权之外,它几乎是替代品.请看这里的例子.