我应该使用 unique_ptr 来保留 class' 成员吗?
Should I use unique_ptr to keep class' members?
我有这样的代码:
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()) //...
{
}
Class A
取得自己对象的所有权 b
、c
、d
...
保存这些物品的最佳方式是什么?我想,std::unique_ptr<B/C/D>
类型的用法将适合这种方式。例如,它允许不关心析构函数的仔细编写。
最好按价值保留所有内容。如果它适合*,并且不需要隐藏**。如果不适合或需要隐藏,第一选择是 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>(...)) {}
};
it allows to don't care about carefull writing of destructor.
不止于此。
您的代码不是异常安全的。例如,如果 new D()
因抛出异常而失败,则 delete b
和 delete c
将不会执行并且内存将泄漏,因为如果构造函数失败则不会调用析构函数。 Smart pointers可以帮助您避免这种情况。
持有原始指针作为成员需要仔细实现析构函数,复制构造函数和赋值等。见 What is The Rule of Three? and Rule-of-Three becomes Rule-of-Five with C++11?.
我觉得值得一提的是,如果你不想转让所有权,你必须使用const std::unique_ptr
。使用非常量 std:unique_ptr
允许将其传输到另一个 std: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()) //...
{
}
Class A
取得自己对象的所有权 b
、c
、d
...
保存这些物品的最佳方式是什么?我想,std::unique_ptr<B/C/D>
类型的用法将适合这种方式。例如,它允许不关心析构函数的仔细编写。
最好按价值保留所有内容。如果它适合*,并且不需要隐藏**。如果不适合或需要隐藏,第一选择是 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>(...)) {}
};
it allows to don't care about carefull writing of destructor.
不止于此。
您的代码不是异常安全的。例如,如果
new D()
因抛出异常而失败,则delete b
和delete c
将不会执行并且内存将泄漏,因为如果构造函数失败则不会调用析构函数。 Smart pointers可以帮助您避免这种情况。持有原始指针作为成员需要仔细实现析构函数,复制构造函数和赋值等。见 What is The Rule of Three? and Rule-of-Three becomes Rule-of-Five with C++11?.
我觉得值得一提的是,如果你不想转让所有权,你必须使用const std::unique_ptr
。使用非常量 std:unique_ptr
允许将其传输到另一个 std:unique_ptr
.