6
votes

I have a C++ application which makes extensively use of pointers to maintain quite complex data structures. The application performs mathematical simulations on huge data sets (which could take several GB of memory), and is compiled using Microsoft's Visual Studio 2010.

I am now reworking an important part of the application. To reduce errors (dangling pointers, memory leaks, ...) I would want to start using smart pointers. Sacrificing memory or performance is acceptible as long as it is limited.

In practice most of the classes are maintained in big pools (one pool per class) and although the classes can refer to each other, you could consider the pool as owner of all the instances of that class. However, if the pool decides to delete an instance, I don't want any of the other classes that still refers to the deleted instance to have a dangling pointer.

In another part I keep a collection of pointers to instances that are delivered by other modules in the application. In practice the other modules maintain ownership of the passed instance, but in some cases, modules don't want to take care of the ownership and just want to pass the instance to the collection, telling it "it's yours now, manage it".

What is the best way to start introducing smart pointers? Just replacing pointers [at random] with smart pointers doesn't seem a correct way, and probably doesn't deliver all the (or any of the) advantages of smart pointers. But what is a better method?

Which types of smart pointers should I further investigate? I sometimes use std::auto_ptr for the deallocation of locally allocated memory, but this seems to be deprected in C++0x. Is std::unique_ptr a better alternative? Or should I go straight to shared pointers or other types of smart pointers?

The question Replacing existing raw pointers with smart pointers seems similar but instead of asking how easy it is, I am asking what the best approach would be, and which kind of smart pointers are suited best.

Thanks in advance for your ideas and suggestions.

2

2 Answers

3
votes

I recommend using unique_ptr when possible (this may require some program analysis) and shared_ptr when this is impossible. When in doubt, use a shared_ptr to maximize safety: when handing off control to a container, the reference count will simply go to two and then back to one and the container will eventually delete the associated object automatically. When performance becomes an issue, consider using boost::intrusive_ptr.

1
votes

Here are the 3 varieties found in the new C++11 standard (unique_ptr replaces auto_ptr)

http://www.stroustrup.com/C++11FAQ.html#std-unique_ptr

http://www.stroustrup.com/C++11FAQ.html#std-shared_ptr

http://www.stroustrup.com/C++11FAQ.html#std-weak_ptr

You can read the text for each pointer and there is an explanation of when to use which in there. For local memory management unique_ptr is the choice. It is non-copyable but movable so as you move it around the receiver takes ownership of it.

Shared_ptr is used if you want to share an object instance around with no one really owning the object and to make sure it doesn't get deleted while someone still has a reference to it. Once the last user of an object destroys the shared_ptr container, the contained object will be deleted.

weak_ptr is used in conjunction with shared_ptr. It enables one to "lock" to see if the reference shared_ptr object still exists before trying to access the internal object.