Reputation: 4512
I have such code:
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
takes ownership over own objects b
, c
, d
...
What is the best way to keep these objects? I guess, that usage of std::unique_ptr<B/C/D>
type will be suitable for this way. For example, it allows to don't care about carefull writing of destructor.
Upvotes: 1
Views: 2568
Reputation: 1552
I think it's worth mentioning that if you do not want to transfer ownership, you must use const std::unique_ptr
. Using a non-const std:unique_ptr
allows to transfer it to another std:unique_ptr
.
Upvotes: 2
Reputation: 172934
it allows to don't care about carefull writing of destructor.
More than that.
Your code is not exception-safe. For example, if new D()
failed by exception being thrown, delete b
and delete c
won't be executed and memory will leak, because destructor won't be called if constructor fails. Smart pointers can help you to avoid this kind of situation.
Holding raw pointer as members you need to implement destructor carefully, and copy constructor and assignment etc too. See What is The Rule of Three? and Rule-of-Three becomes Rule-of-Five with C++11?.
Upvotes: 6
Reputation: 18864
Best is to keep everything by value. If it fits*, and does not need to be hidden**. If it does not fit or needs to be hidden first preference is std::unique_ptr
***, second preference (if ownership has to be shared) is std::shared_ptr
. And only as a last resort (example for which I cannot even think up). You would actually have raw pointers and manage lifetime yourself, with risk of memory errors and leaks.
* - sometimes you want to be able to have parent object on stack by value and child objects are, say, large arrays which, if stored by value would overflow the stack
** - sometimes you don't want to show what child objects really are (because they are complex, say boost.fusion adapted classes. Then you would want some form of PIMPL idiom:
class.hpp
struct b;
struct A { std::unique_ptr<b> b_; A(); ~A(); }
class.cpp:
struct b { ... }
A::A() = default;
A::~A() = default;
*** - automatic management of dynamically allocated members with unique_ptr
struct A {
std::unique_ptr<b> b_;
A(...):
b_(std::make_unique<b>(...)) {}
};
Upvotes: 5