A Smart Pointer is a C++ object that acts like a pointer, but additionally deletes the object when it is no longer needed.

"No longer needed" is hard to define, since resource management in C++ is very complex. Different smart pointer implementations cover the most common scenarios. Of course, different tasks than just deleting the object can be implemented too, but these applications are beyond the scope of this tutorial.

Many libraries provide smart pointer implementations with different advantages and drawbacks. The samples here use the BOOST library, a high quality open source template library, with many submissions considered for inclusion in the next C++ standard.

Boost provides the following smart pointer implementations:

shared_ptr<T>

pointer to T" using a reference count to determine when the object is no longer needed. shared_ptr is the generic, most versatile smart pointer offered by boost.

scoped_ptr<T>

a pointer automatically deleted when it goes out of scope. No assignment possible, but no performance penalties compared to "raw" pointers

intrusive_ptr<T>

another reference counting pointer. It provides better performance than shared_ptr, but requires the type T to provide its own reference counting mechanism.

weak_ptr<T>

a weak pointer, working in conjunction with shared_ptr to avoid circular references

scoped_ptr is the simplest smart pointer provided by boost. It guarantees automatic deletion when the pointer goes out of scope.

A note on the samples:

The samples use a helper class, CSample, that prints diagnostic messages when it it constructed, assigned, or destroyed. Still it might be interesting to step through with the debugger. The sample includes the required parts of boost, so no additional downloads are necessary - but please read the boost installations notes, below.

Using "normal" pointers, we must remember to delete it at every place we exit the function. This is especially tiresome (and easily forgotten) when using exceptions. The second example uses a scoped_ptr for the same task. It automatically deletes the pointer when the function returns 8 even in the case of an exception thrown, which isn't even covered in the "raw pointer" sample!)

The advantage is obvious: in a more complex function, it's easy to forget to delete an object. scoped_ptr does it for you. Also, when dereferencing a NULL pointer, you get an assertion in debug mode.

Reference counting pointers track how many pointers are referring to an object, and when the last pointer to an object is destroyed, it deletes the object itself, too.

The "normal" reference counted pointer provided by boost is shared_ptr (the name indicates that multiple pointers can share the same object). Let's look at a few examples:

void Sample2_Shared()
{
// (A) create a new CSample instance with one reference
boost::shared_ptr<CSample> mySample(new CSample);
printf("The Sample now has %i references\n", mySample.use_count()); // should be 1
// (B) assign a second pointer to it:
boost::shared_ptr<CSample> mySample2 = mySample; // should be 2 refs by now
printf("The Sample now has %i references\n", mySample.use_count());
// (C) set the first pointer to NULL
mySample.reset();
printf("The Sample now has %i references\n", mySample2.use_count()); // 1
// the object allocated in (1) is deleted automatically
// when mySample2 goes out of scope
}

Line (A) creates a new CSample instance on the heap, and assigns the pointer to a shared_ptr, mySample. Things look like this:

Then, we assign it to a second pointer mySample2. Now, two pointers access the same data:

We reset the first pointer (equivalent to p=NULL for a raw pointer). The CSample instance is still there, since mySample2 holds a reference to it:

Only when the last reference, mySample2, goes out of scope, the CSample is destroyed with it:

Of course, this is not limited to a single CSample instance, or two pointers, or a single function. Here are some use cases for a shared_ptr.

use in containers

using the pointer-to-implementation idiom (PIMPL)

Resource-Acquisition-Is-Initialization (RAII) idiom

Separating Interface from Implementation

Note: If you never heard of PIMPL (a.k.a. handle/body) or RAII, grab a good C++ book - they are important concepts every C++ programmer should know. Smart pointers are just one way to implement them conveniently in certain cases - discussing them here would break the limits of this article.

The boost::shared_ptr implementation has some important features that make it stand out from other implementations:

shared_ptr<T> works with an incomplete type:

When declaring or using a shared_ptr<T>, T may be an "incomplete type". E.g., you do only a forward declaration using class T;. But do not yet define how T really looks like. Only where you dereference the pointer, the compiler needs to know "everything".

shared_ptr<T> works with any type:

There are virtually no requirements towards T (such as deriving from a base class).

shared_ptr<T> supports a custom deleter

So you can store objects that need a different cleanup than delete p. For more information, see the boost documentation.

Implicit conversion:

If a type U * can be implicitly converted to T * (e.g., because T is base class of U), a shared_ptr<U> can also be converted to shared_ptr<T> implicitly.

shared_ptr is thread safe

(This is a design choice rather than an advantage, however, it is a necessity in multithreaded programs, and the overhead is low.)

Many container classes, including the STL containers, require copy operations (e.g., when inserting an existing element into a list, vector, or container). However, when this copy operations are expensive (or are even unavailable), the typical solution is to use a container of pointers:

Very similar, but now, the elements get destroyed automatically when the vector is destroyed - unless, of course, there's another smart pointer still holding a reference. Let's have a look at sample 3:

A few things can go wrong with smart pointers (most prominent is an invalid reference count, which deletes the object too early, or not at all). The boost implementation promotes safety, making all "potentially dangerous" operations explicit. So, with a few rules to remember, you are safe.

There are a few rules you should (or must) follow, though:

Rule 1: Assign and keep - Assign a newly constructed instance to a smart pointer immediately, and then keep it there. The smart pointer(s) now own the object, you must not delete it manually, nor can you take it away again. This helps to not accidentally delete an object that is still referenced by a smart pointer, or end up with an invalid reference count.

Rule 2: a _ptr<T> is not a T * - more correctly, there are no implicit conversions between a T * and a smart pointer to type T.

This means:

When creating a smart pointer, you explicitly have to write ..._ptr<T> myPtr(new T)

You cannot assign a T * to a smart pointer

You cannot even write ptr=NULL. Use ptr.reset() for that.

To retrieve the raw pointer, use ptr.get(). Of course, you must not delete this pointer, or use it after the smart pointer it comes from is destroyed, reset or reassigned. Use get() only when you have to pass the pointer to a function that expects a raw pointer.

You cannot pass a T * to a function that expects a _ptr<T> directly. You have to construct a smart pointer explicitly, which also makes it clear that you transfer ownership of the raw pointer to the smart pointer. (See also Rule 3.)

Rule 2: No circular references - If you have two objects referencing each other through a reference counting pointer, they are never deleted. boost provides weak_ptr to break such cycles (see below).

Rule 3: no temporary shared_ptr - Do not construct temporary shared_ptr to pass them to functions, always use a named (local) variable. (This makes your code safe in case of exceptions. See the boost: shared_ptr best practices for a detailed explanation.)

Reference counting is a convenient resource management mechanism, it has one fundamental drawback though: cyclic references are not freed automatically, and are hard to detect by the computer. The simplest example is this:

parent still references the CDad object, which itself references the CChild. The whole thing looks like this:

If we now call dad.reset(), we lose all "contact" with the two objects. But this leaves both with exactly one reference, and the shared pointers see no reason to delete either of them! We have no access to them anymore, but they mutually keep themselves "alive". This is a memory leak at best; in the worst case, the objects hold even more critical resources that are not released correctly.

The problem is not solvable with a "better" shared pointer implementation (or at least, only with unacceptable overhead and restrictions). So you have to break that cycle. There are two ways:

Manually break the cycle before you release your last reference to it

When the lifetime of Dad is known to exceed the lifetime of Child, the child can use a normal (raw) pointer to Dad.

Use a boost::weak_ptr to break the cycle.

Solutions (1) and (2) are no perfect solutions, but they work with smart pointer libraries that do not offer a weak_ptr like boost does. But let's look at weak_ptr in detail:

A strong reference keeps the referenced object alive (i.e., as long as there is at least one strong reference to the object, it is not deleted). boost::shared_ptr acts as a strong reference. In contrast, a weak reference does not keep the object alive, it merely references it as long as it lives.

Note that a raw C++ pointer in this sense is a weak reference. However, if you have just the pointer, you have no ability to detect whether the object still lives.

boost::weak_ptr<T> is a smart pointer acting as weak reference. When you need it, you can request a strong (shared) pointer from it. (This can be NULL if the object was already deleted.) Of course, the strong pointer should be released immediately after use. In the above sample, we can decide to make one pointer weak:

shared_ptr offers quite some services beyond a "normal" pointer. This has a little price: the size of a shared pointer is larger than a normal pointer, and for each object held in a shared pointer, there is a tracking object holding the reference count and the deleter. In most cases, this is negligible.

intrusive_ptr provides an interesting tradeoff: it provides the "lightest possible" reference counting pointer, if the object implements the reference count itself. This isn't so bad after all, when designing your own classes to work with smart pointers; it is easy to embed the reference count in the class itself, to get less memory footprint and better performance.

To use a type T with intrusive_ptr, you need to define two functions: intrusive_ptr_add_ref and intrusive_ptr_release. The following sample shows how to do that for a custom class:

They are almost identical to scoped_ptr and shared_ptr - only they act like pointers to arrays, i.e., like pointers that were allocated using operatornew[]. They provide an overloaded operator[]. Note that neither of them knows the length initially allocated.

Download the current boost version from boost.org, and unzip it to a folder of your choice. The unzipped sources use the following structure (using my folders):

boost\

the actual boost sources / headers

doc\

the documentation of the current version, in HTML format

libs\

libraries (not needed for

....

some more odd bits and ends ("more\" has some interesting stuff)

I add this folder to the common includes of my IDE:

in VC6, this is Tools/Options, Directories tab, "Show Directories for... Include files",

in VC7, this is Tools/Options, then Projects/VC++ directories, "Show Directories for... Include files".

Since the actual headers are in the boost\ subfolder, my sources has #include "boost/smart_ptr.hpp". So everybody reading the source code knows immediately you are using boost smart pointers, not just any ones.

The sample project contains a sub folder boost\ with a selection of boost headers required. This is merely so you can download and compile the sample. You should really download the complete and most current sources (now!).

There is a "little" problem with VC6 that makes using boost (and other libraries) a bit problematic out of the box.

The Windows header files define macros for min and max, and consequently, these respective functions are missing from the (original) STL implementation. Some Windows libraries such as MFC rely on min/max being present. Boost, however, expects min and max in the std:: namespace. To make things worse, there is no feasible min/max template that accepts different (implicitly convertible) argument types, but some libraries rely on that.

boost tries to fix that as good as they can, but sometimes you will run into problems. If this happens, here's what I do: put the following code before the first include:

Articles on Code Project:

Designing Robust Objects with boost by Jim D'Agostino, a very interesting article: it seems to cover too much topics at once, but it excels at showing how different tools, mechanisms, paradigms, libraries, etc. work together.

Please note: While I am happy about (almost) any feedback, please do not ask boost-specific questions here. Simply put, boost experts are unlikely to find your question here (and I'm just a boost noob). Of course, if you have questions, complaints, or recommendations regarding the article or the sample project, you are welcome.

Share

About the Author

Peter is tired of being called "Mr. Chen", even so certain individuals insist on it. No, he's not chinese.

Peter has seen lots of boxes you youngsters wouldn't even accept as calculators. He is proud of having visited the insides of a 16 Bit Machine.

In his spare time he ponders new ways of turning groceries into biohazards, or tries to coax South American officials to add some stamps to his passport.

Beyond these trivialities Peter works for Klippel[^], a small german company that wants to make mankind happier by selling them novel loudspeaker measurement equipment.

Where are you from?[^]Please, if you are using one of my articles for anything, just leave me a comment. Seeing that this stuff is actually useful to someone is what keeps me posting and updating them.Should you happen to not like it, tell me, too

Hi, you mentioned that constructing temporary shared_ptr to pass pointers to functions is discouraged, yet you used it in your container sample. I checked the boost document, where they use APtr.reset(new A) for this task. That being said, I still couldn't see where it could go wrong with your way of passing smart pointers

if new Y fails (out of memory, or CTor exception), the first allocaiton leaks, because it wasn't yet assigned to an XPtr. Note that any throwing subexpression that may be evaluated between the allocation and the respective CTor may cause the leak, it doesn't have to be two smart pointer intializations.

Now, in the container example there is no such code path (at least, in my understanding of the standard). So I am using here my deeper understanding to violate the rule I proposed - that's definitely bad style.

This is a good point.
It should be:
CDadPtr parent(new CDad);
CChildPtr child(new CChild);
I think.
I see that Peter hasn't updated the article, talking about the previous issue about Cyclic Reference, and it really MUST BE done, cause this is the top Google-rated article about the subject, so many will learn from it for the first time.
I was doing it too, so thanks Peter for the quickest tutorial about this (and please consider the previous request)
Cheers

Because using an auto_ptr would compile, but do the wrong thing, for the automatically generated functions. Using scoped_ptr makes it much more difficult to accidentally overlook the copying semantics [...]

The article mentions that scoped_ptr and shared_ptr can be used to implement PIMPL idiom (implementation hiding in header files).

This is true... with small limitations for scoped_ptr. Since the explanation was not obvious for me (explanations I found on the net were more misleading), I'll try to document it here.
A scoped_ptr can be used with an incomplete type, but not destruct an incomplete type. This is not a real problem, still it is good to know the limitations: In the compilation unit where the destruction of the scoped_ptr is actually instantiated, the to be destructed object needs to be complete. The scoped_ptr will check this for you at compile time (via boost::checked_delete) so you won't run into problems! Kinda brain twisting, hope I summarised it correct.

All the label says is that this stuff contains chemicals "... known to the State of California to cause cancer in rats and low-income test subjects." Roger Wright http://www.codeproject.com/lounge.asp?select=965687&exp=5&fr=1#xx965687xx

The reference counter is open for race conditions. E.g., if you delete the last and second last smart pointers to an object, the object will be delete zero, one or two times. And if you create and/or delete smart pointers simultaneously in parallel threads, the reference counter value may be corrupted.

Access to the pointed to data is allowed, but will cause clashes for any non-atomic operations, such as assignment to non-primitive types or sequences of operations on primitive types.
Ex:

provided you #define BOOST_HAS_THREADS.
The config headers define that by default for target platforms they know. (Including our beloved VC6/VC7 when you compile with Multithreaded Runtime).

This has been added only recently (Release 1.30 I think).

Of course, the boost implementation only protectes the reference counter itself. If you usethem in different threads, the object pointed to must be threadsafe, or access to the object must be serialized. (This is the same as you would have to do for a "raw" pointer)

we are here to help each other get through this thing, whatever it is Vonnegut jr.

The reference counter is open for race conditions. E.g., if you delete the last and second last smart pointers to an object, the object will be delete zero, one or two times.

If the last and second to last boost::shared_ptr pointing to the same object go out of scope (or are reassigned, etc.) the object is thread-safely deleted. Why do you think it does otherwise? reference count is locked when in a multi-threaded environment, see http://boost.org/libs/smart_ptr/shared_ptr.htm#ThreadSafety[^].

And if you create and/or delete smart pointers simultaneously in parallel threads, the reference counter value may be corrupted.

Again, adding references to a common object is perfectly thread-safe.

Access to the pointed to data is allowed, but will cause clashes for any non-atomic operations, such as assignment to non-primitive types or sequences of operations on primitive types.

This is true, yes. But this level of thread unsafety has nothing to do with boost::shared_ptr. Basically, atomicity is a concept relative to what your application considers as an atomic operation. In some cases, atomicity at the level of member function is good enough, sometimes you'll want a higher level concept. For that reason, it is IMHO good practice not to burden the user with any kind of built-in atomicity support: you can always build your own with external mecnahinsm (locks and stuff) or internally in the object itself.

Consider your example:

if (10 == *p_int) {
*p_int = 20; // *p_int may no longer be 10!
}

Of course *p_int may no longer be 10! What is the alternative, that *p_int be 10 forever? boost::shared_ptr has no way to know whether you want the object to be locked till the next write of until the end of time. Clearly, this is an app-level issue and it is the programmer that must provide her locking scheme. I hope I got my point through, more or less

Sorry for replying almost 3 years later but Yesterday I was debugging some code that uses a very similar designed shared pointer and as I stepped through the code I thought it definitely was not thread safe as it only ensured that the reference count was correct but as it appeared to me this could cause double deletes and really weird stuff if copys are going on while a delete as you mentioned in your post. As it turns out the first case can not be true as long as each thread has its own shared_ptr (even if each shared ptr points to the same object). The reason is that in this case both reference counts can not be zero so only the last one will take. The second case would have a similar reason why thread safety is achieved. The docs do say this but it is confusing at first read. Here is the quote that mentions that:

Thread Safety

shared_ptr objects offer the same level of thread safety as built-in types. A shared_ptr instance can be "read" (accessed using only const operations) simultaneously by multiple threads. Different shared_ptr instances can be "written to" (accessed using mutable operations such as operator= or reset) simultaneosly by multiple threads (even when these instances are copies, and share the same reference count underneath.)

The link as mentioned by another user is here: http://boost.org/libs/smart_ptr/shared_ptr.htm#ThreadSafety

(1) Imagine that thread1 just copied 'px' member of shared_ptr but then was interrupted. Then thread2 might replace both 'px' and 'pn' with another object data. When thead1 gains control and copy new 'pn' member value - the pointer would become inconsistent.

(2) Imagine that thead1 just copied px and gained a pointer to reference counter but haven't incremented it yet. It might happen that thread3 would interrupt it, destroy object and its counter, and then thread1() would operate on already deallocated memory...

So, not only reference counter should be accessed in an atomic manner, but the whole operation of copying or resetting that kind of pointer should be protected with a kind of many readers - single writer lock.

Your analysis is correct - but what you are asking for is not thread safety of smart pointers.

Boost does not magically work around "when sharing data between threads, you need to synchronize access". It merely provides what you would expect from a pointer: manipulating different pointers to the same data in separate threads does not require additional synchronization:

and your results are undefined, whether you use raw or smart pointers.

Your example makes the object pointer itself shared between threads. In above example, assigning a different value to foop is not thread safe either. The assignment is - under normal circumstances1) - atomic, i.e. you get no garbage, but that doesn't guarantee thread safety: when or even if other threads see the change is undefined. 2)

Access to shared data requires an explicit lock, or at least an Interlocked statement (that's one disadvantage of shared_ptr: it can't be used with interlocked. intrusive_ptr lets you, though.)

So, why doesn't shared_ptr use a lock for that assignment to make it safe?
First, you should not expect it from a raw pointer, either. (Many people do, and it works on many architectures, but the code is still not correct).

Second, locks on individual data elements are usually not useful. If your object pointer is part of a data integrity requirement like this:

atomic assignment of foop doesn't buy you anything, but it costs you another lock. You still need to lock the assignment operator, though.

I understand that this topic isn't easy, and saying "boost smart pointers are thread safe" might create expectations that are not justified.
I also don't claim to fully understand that, I'd like to discuss this and if there seems to be consensus, I'd add a section to this article.

1) normal here means: the pointer is aligned at an address that is a multiple of its size.
2) The CPU cache is the bad boy: if threads are assigned to different cores with individual data caches, they are not in sync. See the doublechecked locking pattern si broken declaration for an exercise how bad the situation is. In above examples - both yours and mine - the thread creation provides the necessary sync point.

Well, your explanation is absolutely clear and complete. Thank you! =) I really needed someone to agree that I'm not being lost in multithreading issues ,)

Actually, the origin of the problem is: I'm thinking about a concept of a smart pointer that would allow efficient thread-safe access to its contents.

I need it for two major tasks:

- pointer to a service which can be asynchroniously changed or disabled (so, I would take a copy of a pointer to service before using it; and I will simple reset or replace it as soon as the service should be disabled or changed, and all threads will sooner or later release their local copies and service would become free of references);

- lock-free module parameters substitution, when I would prepare new parameters for some algorithm and provide them with a single atomic assignment;

Still, I think even intrusive_ptr doesn't solve this. Because two operations - copy and AddRef - can not be done with a single interlocked -)

So, I guess I would eventually introduce two kinds of pointers (as policy template parameter): thread-unsafe and thread-safe (with an internal RW-lock).

The C++ gurus (Andrescu or Myers, not sure) had a lengthy article about auto-locking smart pointers in a Dr. Dobbs column. Here[^] is a short intro into pointee locking, the article was more in detail and discussed different problems.

kills it. if you could prevent destruction (e.g. guaranteeing another existing refcount), you might get it to work, but that kind of defeats the point I guess.

"Some lock" when accessing the global instance is unevitable. I still wonder if there's some Interlocked trickery to implement that (state free, or with state embedded in the pointee), but it doesn't look good.

I've found ZooLib[^] claiming to have a "truly threadsafe" pointer, but as I understand the source comments, it uses as shared mutex to protect all (!) reference counting activity. Not what you are looking for

Yes, there subtle places in smart_ptr usage rules =)
Maybe it's even worth noting that fact somewhere in the article?

RW-lock would be appropriate, I think... Any reader should gain read-lock for the period of copy-addref, and write-lock would be taken for the period of interlockedExchange with another (referenced) pointer (or zero). Release can be called without any locks acquired.

Interesting enough: concurrent writes are allowed =) But that's logical, since atomicity of remove-release is not required.

So the lock is still required even for intrusive_ptr to be used concurrently. But using the same idea makes shared_ptr equally safe (but slightly larger amount of operation should be done concurently).

Only multithreading-safe smart pointers should have that overhead, which might be implemented by a policy template parameter.

Global lock is not a good idea for a large SMP application. We'll have spin-lock with each "safe" pointer and an event to wait, in case spin-lock would freeze for too long (most possibly that would be an exteremely rare situation).

Loki: I see that their CSmartPtr is more powerful, and can in fact replace boost smart_ptr. But my problems with it are outside the domain of C++ design choices.
I personally prefer the "less template, more classes" approach. Policy-Based template design is cool, but I have to work with real-life compilers. A smart pointer is just the lowest step stone of a large project (and large ones are the ones that need it). If already my basic library brings my compiler and debugger to the limits, I end up fighting more administrative than customer problems. Further, I think Loki lacks what boost.org is to boost.

it's not only that the VC6 I'm stuck with comes with mediocre template support. It's mostly diagnostic tools, like compiler error messages and debug watch window, call stack etc. Any extra layer in the fundamental classes (even if removed by the compiler) adds a factor of 2 workload for certain tasks. Compile times can skyrocket with overly templated code (I'm building daily). And, Template complexity, beyond the dream of the perfect compiler, limits portability.

Some weeks ago I asked for a Boost-devoted forum to be set up at CP, with alas not much response. But the fact that this article rating has sky rocketed shows IMHO that there's a real niche for assisting Boost newbies here at CP. Excuse my insistence, but shouldn't we consider the issue again?

my understanding is that, the objective of the design of boost ptr should be taking care of the "laziness" or more like "safety" of using it. as u said, it is not "master template". may be someone could improve the automated feature into it.
well, if one would like to have all the automated feature, what is its overhead?

The problem you mention (ambiguity between new[] and new) is deeply rooted in the language, and not solvable within the restrictions of the language. YOU, the programmer have to know it.*)

No amount of coding can turn C++ into an unbreakabke language. The fundamental idea of "smart" classes is: act like a built-in concept (e.g. a pointer), but provide additional services. Reusing (instead of replacing) a built-in concept makes them so powerful: it allows to reuse (rather than extend) your knowledge, common concepts, etc. But this way you also inherit the weaknesses of the concept.

*) As a side note: smart pointers make that easier: you need to make the correct decision at one place (declaration of the scope_xxxx), instead of two places (new/new[] and delete/delete[])

we are here to help each other get through this thing, whatever it is Vonnegut jr.

yes. totally agreed.
my stand point is to make migration easier and transparent. ie, minimum code changes and transparent to other developer who access to the same project.
since as u said the problem is rooted in the language itself, so i assume it is hardly implemented/fan-out onto old projects.
of cause starting a new project will have better benefit rather than patching up the old one.

In short, download boost and bjam binaries from sourceforge
- unzip boost
- unzip the bjam binaries into the same folder as boost,
- bjam.exe needs to be in the same folder as the boost root directory
- open the visual studio command prompt
- navigate to the boost root directory

type:

bjam "-sTOOLS=vc7.1" install
OR
bjam "-sTOOLS=vc7" install

- the boost.python installation will probably fail, but it's easier to use the solutions to build it afterwards
- leave it for about 20 minutes
- done

If you can keep you head when all about you
Are losing theirs and blaming it on you;
If you can dream - and not make dreams your master;
If you can think - and not make thoughts your aim;
Yours is the Earth and everything that's in it.

That's true. I could not make it working so I decided to use smartpointer from loki in my Generic Pool :Policy based design article. Loki smart pointer is very easy to use.
You can see my article : http://www.codeproject.com/library/Generic_Pool_Design.asp