我应该使用unique_ptr来保持班级成员吗?

时间:2016-05-25 14:07:00

标签: c++ pointers smart-pointers unique-ptr

我有这样的代码:

class A
{
public:
    A(void);
    ~A(void)
    {
        delete b;
        delete c;
        delete d;
        // ...
    }
private:
    B* b;
    C* c;
    D* d;
    // ...
};

//A.cpp
    A(void) : b(new B()), c(new C()), d(new D()) //...
    {  
    }

班级A拥有对象bcd的所有权... 保留这些物体的最佳方法是什么?我想,std::unique_ptr<B/C/D>类型的使用将适合这种方式。例如,它允许不关心析构函数的仔细编写。

3 个答案:

答案 0 :(得分:6)

  

它允许不小心谨慎地编写析构函数。

不止于此。

  1. 您的代码不是异常安全的。例如,如果抛出异常导致new D()失败,则delete bdelete c将无法执行并且内存将泄漏,因为如果构造函数失败则不会调用析构函数。 Smart pointers可以帮助您避免这种情况。

  2. 将原始指针作为成员保存,您需要仔细实现析构函数,并复制构造函数和赋值等。请参阅What is The Rule of Three?Rule-of-Three becomes Rule-of-Five with C++11?

答案 1 :(得分:4)

最好是按价值保持一切。如果它适合*,并且不需要隐藏**。如果它不适合或需要隐藏,则首选项为std::unique_ptr ***,第二个首选项(如果必须共享所有权)为std::shared_ptr。并且只作为最后的手段(我甚至无法想到的例子)。实际上你会有自己的原始指针和管理生命周期,存在内存错误和泄漏的风险。

* - 有时你希望能够通过值在堆栈上拥有父对象,而子对象就是大型数组,如果按值存储则会溢出堆栈

** - 有时你不想显示真正的子对象(因为它们很复杂,比如说boost.fusion改编的类。那么你会想要某种形式的PIMPL习语:

class.hpp
struct b;
struct A { std::unique_ptr<b> b_; A(); ~A(); }

class.cpp:
struct b { ... }
A::A() = default;
A::~A() = default;

*** - 使用unique_ptr

自动管理动态分配的成员
struct A {
  std::unique_ptr<b> b_;
  A(...):
    b_(std::make_unique<b>(...)) {}
};

答案 2 :(得分:1)

我认为值得一提的是,如果您不想转让所有权,则必须使用const std::unique_ptr。使用非const std:unique_ptr可以将其转移到另一个std:unique_ptr