I am busy designing a new C++ application. In this application I want to minimize potential errors with pointers, and since the application should be plain C++ (no .Net or other fancy things), I am investigating shared pointers and I am considering using shared pointers everywhere (instead of normal pointers).
I worked out some tricks to make it easier to work with shared pointers, e.g.: using a typedef within the class, like this:
class X
{
public:
...
typedef std::shared_ptr<X> Ptr;
};
That way you can easily write X::Ptr, which is easier to write than “std::shared_ptr” everywhere.
I also noticed some disadvantages to shared pointers:
- Everywhere I use a shared pointer I need to include
<memory> - I can’t use forward declaration anymore if I just want to use the pointer
Are there any other tricks to make shared pointers easier to work with?
DON’T!
The only way to minimize pointer errors is to use the right pointer types. And that’s types, plural.
Shared pointers are not a silver bullet. They become memory leaks as soon when you have cyclical references (and if plan to use them everywhere, those will show up pretty quickly)
If you want error-free C++ applications, you have to work for it. You have to understand your application. You have to understand the ownership semantics of different objects. Shared pointers just give you shared ownership, which is generally a decent lowest denominator. Everything else can be replaced by shared ownership and it’ll work, sort of.
But the default case is that an object is owned by one other entity. It is owned by a function, and should be destroyed when that function returns, or it is owned by a class, or whatever else. Often, you don’t need pointers at all. the object is stored by value in a
std::vector, perhaps. Or it is just a local variable or a class member. If it is a pointer, it’ll often be better expressed by ascoped_ptror perhaps one which allows transfer of ownership (unique_ptrorauto_ptr).shared_ptris what you might fall back to when you can give no guarantees about the lifetime or ownership of an object. But when you use that, you also need to useweak_ptrto break cycles.Really, a better approach is to avoid pointers as much as at all possible. When you do need a pointer, use one which has the most specific ownership semantics possible (prefer
scoped_ptr, which doesn’t allow transfer of ownership at all, then if you need it, fall back to one which allows you to move ownership, such asunique_ptr, and only as a last resort should you useshared_ptr, which allows you to share ownership freely among any number of clients.There’s no magic wand you can wave to make your C++ code “just work”. The only way to achieve that is to write good solid C++ code. And you do that by knowing, and using, the tools at your disposal, not by pretending that “hey,
shared_ptris just like a garbage collector, isn’t it? I can just ignore all questions of object lifetime or memory leaks if I use it”.