This post is very old. Please bear in mind that information here might be incorrect or obsolete, and links can be broken. If something seems wrong, please feel free to comment or contact me and I'll update the post.
The C++ TR1 additions contain an extremely useful smart pointer: std::tr1::shared_ptr. Used properly, it allows creating efficient and safe C++ code without the risk of memory leaks. Point in case: I have a personal project with 10k + LoC without a single delete call.
How to get it, and what it is
std::tr1::shared_ptr is part of the TR1 additions to the C++ STL. With GCC, it is available either through #include <tr1/memory> (GCC 4.1) or #include <memory> (GCC 4.3), the latter form works also on Windows (with VS2008 SP1). If you want to be portable, try Boost, which uses the vendor-provided solution if possible and falls back to a custom one if no vendor solution was found. To use this, just include <boost/tr1/memory.hpp>
Basically, the shared pointer is a reference counted pointer. The references are counted using atomic instructions, so it is (mostly) thread-safe. Exception: If you pass the shared pointer by reference, and it is modified then by two threads, you’ll run into problems, so copy it!
Usage examples
Let us take a look at several usage examples.
Deleting an array
An array can be deleted by providing a custom array deleter.
template
class ArrayDeleter
{
public:
void operator () (T* d) const
{
delete [] d;
}
};
int main ()
{
// Usage
std::tr1::shared_ptr array (new double [256], ArrayDeleter ());
}
or, if you have Boost and included <boost/smart_ptr.hpp> and you need a temporary array
boost::scoped_array array (new double [256]);
scoped_array is noncopyable, which makes it perfect for local buffers.
Casting
It is possible to cast shared pointers using std::tr1::dynamic_pointer_cast and std::tr1::static_pointer_cast.
class Base
{
};
class Derived : public Base
{
};
int main ()
{
std::tr1::shared_ptr base (new Derived ());
// Static downcast
std::tr1::shared_ptr derived = std::tr1::static_pointer_cast (base);
}
Custom reference counting
If your class has custom reference counting (COM, anyone?), you can still use shared pointers for it.
class CustomReferenceCounted
{
public:
CustomReferenceCounted (int* counter)
: counter_ (counter)
{
}
void Release ()
{
--(*counter_);
}
private:
int* counter_;
};
class CustomReferenceCountedDeleter
{
public:
void operator () (CustomReferenceCounted* r) const
{
r->Release ();
// So we don't leak memory in this example
delete r;
}
};
int main()
{
int counter = 1;
std::tr1::shared_ptr crc (new CustomReferenceCounted (&counter), CustomReferenceCountedDeleter ());
crc.reset ();
std::cout << counter << std::endl;
}
Usage notes
There is a slight performance hit for the shared pointer copying, so you should pass the contained object by reference (preferably) or pointer unless the called code needs a copy of the pointer (for example, when inserting into a container).
Being reference-counted, you cannot use shared pointers for cyclic data structures directly. For this, you can fall back to weak_ptr, which does not prevent deleting the pointed-to object but allows promoting to a shared pointer if needed. For a big list of more tricks, take a look at the Boost shared_ptr documentation.
[Update] Change the link to automatically point to the latest Boost documentation.
Related posts:
You still need to include to get std::tr1::shared_ptr in GCC 4.3
You can get std::shared_ptr by including if you enable the experimental C++0x support with -std=c++0x, but you still don’t get std::tr1::shared_ptr unless you include
Gah … that should have read …
You still need to include <tr1/memory> to get std::tr1::shared_ptr in GCC 4.3
You can get std::shared_ptr by including <memory> if you enable the experimental C++0x support with -std=c++0x, but you still don’t get std::tr1::shared_ptr
My bad, yes, you’re right, thanks. With GCC 4.3 there are two ways to get shared_ptrs:
* include
<memory>, which gives you (if using –std=c++0x)std::shared_ptr* include
<tr1/memory>which givesstd::tr1::shared_ptrindependent of the standards modeOf course, you can always use
boost/tr1/memory.hppto be safe in every case.Pingback: auto_ptr,shared_ptr智能指针的使用 « 云海游鱼的Bolg
Pingback: Spaß mit stl::shared_ptr auf ein c-array in C++ (Memory Tester) « Wissenswertes
shared_ptr is not an addition to the STL. It is an addition to the C++ Standard Library.
Standard Library and STL are not the same.