Anteru's blog
  • Consulting
  • Research
    • Assisted environment probe placement
    • Assisted texture assignment
    • Edge-Friend: Fast and Deterministic Catmull-Clark Subdivision Surfaces
    • Error Metrics for Smart Image Refinement
    • High-Quality Shadows for Streaming Terrain Rendering
    • Hybrid Sample-based Surface Rendering
    • Interactive rendering of Giga-Particle Fluid Simulations
    • Quantitative Analysis of Voxel Raytracing Acceleration Structures
    • Real-time Hybrid Hair Rendering
    • Real-Time Procedural Generation with GPU Work Graphs
    • Scalable rendering for very large meshes
    • Spatiotemporal Variance-Guided Filtering for Motion Blur
    • Subpixel Reconstruction Antialiasing
    • Tiled light trees
    • Towards Practical Meshlet Compression
  • About
  • Archive

std::tr1::shared_ptr tutorial

September 01, 2008
  • Programming
approximately 6 minutes to read

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 <typename T>
class ArrayDeleter
{
public:
    void operator () (T* d) const
    {
        delete [] d;
    }
};

int main ()
{
    // Usage
    std::tr1::shared_ptr<double> array (new double [256], ArrayDeleter<double> ());
}

or, if you have Boost and included <boost/smart_ptr.hpp> and you need a temporary array

boost::scoped_array<double> 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> base (new Derived ());

    // Static downcast
    std::tr1::shared_ptr<Derived> derived = std::tr1::static_pointer_cast<Derived> (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<CustomReferenceCounter> 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: Changed the link to automatically point to the latest Boost documentation.

Previous post
Next post

Recent posts

  • Data formats: Why CSV and JSON aren't the best
    Posted on 2024-12-29
  • Replacing cron with systemd-timers
    Posted on 2024-04-21
  • Open Source Maintenance
    Posted on 2024-04-02
  • Angular, Caddy, Gunicorn and Django
    Posted on 2023-10-21
  • Effective meetings
    Posted on 2022-09-12
  • Older posts

Find me on the web

  • GitHub
  • GPU database
  • Projects

Follow me

Anteru NIV_Anteru
Contents © 2005-2025
Anteru
Imprint/Impressum
Privacy policy/Datenschutz
Made with Liara
Last updated February 20, 2019