boost.png (6897 bytes)weak_ptr class template

Introduction
Synopsis
Members
Free Functions
Frequently Asked Questions

Introduction

The weak_ptr class template stores a "weak reference" to an object that's already managed by a shared_ptr. To access the object, a weak_ptr can be converted to a shared_ptr using the shared_ptr constructor or the member function lock. When the last shared_ptr to the object goes away and the object is deleted, the attempt to obtain a shared_ptr from the weak_ptr instances that refer to the deleted object will fail: the constructor will throw an exception of type boost::bad_weak_ptr, and weak_ptr::lock will return an empty shared_ptr.

Every weak_ptr meets the CopyConstructible and Assignable requirements of the C++ Standard Library, and so can be used in standard library containers. Comparison operators are supplied so that weak_ptr works with the standard library's associative containers.

weak_ptr operations never throw exceptions.

The class template is parameterized on T, the type of the object pointed to.

Compared to shared_ptr, weak_ptr provides a very limited subset of operations since accessing its stored pointer is often dangerous in multithreaded programs, and sometimes unsafe even within a single thread (that is, it may invoke undefined behavior.) Pretend for a moment that weak_ptr has a get member function that returns a raw pointer, and consider this innocent piece of code:

shared_ptr<int> p(new int(5));
weak_ptr<int> q(p);

// some time later

if(int * r = q.get())
{
    // use *r
}

Imagine that after the if, but immediately before r is used, another thread executes the statement p.reset(). Now r is a dangling pointer.

The solution to this problem is to create a temporary shared_ptr from q:

shared_ptr<int> p(new int(5));
weak_ptr<int> q(p);

// some time later

if(shared_ptr<int> r = q.lock())
{
    // use *r
}

Now r holds a reference to the object that was pointed by q. Even if p.reset() is executed in another thread, the object will stay alive until r goes out of scope or is reset. By obtaining a shared_ptr to the object, we have effectively locked it against destruction.

Synopsis

namespace boost {

  template<class T> class weak_ptr {

    public:
      typedef T element_type;

      weak_ptr();

      template<class Y> weak_ptr(shared_ptr<Y> const & r);
      weak_ptr(weak_ptr const & r);
      template<class Y> weak_ptr(weak_ptr<Y> const & r);

      ~weak_ptr();

      weak_ptr & operator=(weak_ptr const & r);
      template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r);
      template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r);

      long use_count() const;
      bool expired() const;
      shared_ptr<T> lock() const;

      void reset();
      void swap(weak_ptr<T> & b);
  };

  template<class T, class U>
    bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b);

  template<class T>
    void swap(weak_ptr<T> & a, weak_ptr<T> & b);
}

Members

element_type

typedef T element_type;

Provides the type of the template parameter T.

constructors

weak_ptr();

Effects: Constructs an empty weak_ptr.

Postconditions: use_count() == 0.

Throws: nothing.

template<class Y> weak_ptr(shared_ptr<Y> const & r);
weak_ptr(weak_ptr const & r);
template<class Y> weak_ptr(weak_ptr<Y> const & r);

Effects: If r is empty, constructs an empty weak_ptr; otherwise, constructs a weak_ptr that shares ownership with r as if by storing a copy of the pointer stored in r.

Postconditions: use_count() == r.use_count().

Throws: nothing.

destructor

~weak_ptr();

Effects: Destroys this weak_ptr but has no effect on the object its stored pointer points to.

Throws: nothing.

assignment

weak_ptr & operator=(weak_ptr const & r);
template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r);
template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r);

Effects: Equivalent to weak_ptr(r).swap(*this).

Throws: nothing.

Notes: The implementation is free to meet the effects (and the implied guarantees) via different means, without creating a temporary.

use_count

long use_count() const;

Returns: 0 if *this is empty; otherwise, the number of shared_ptr objects that share ownership with *this.

Throws: nothing.

Notes: use_count() is not necessarily efficient. Use only for debugging and testing purposes, not for production code.

expired

bool expired() const;

Returns: use_count() == 0.

Throws: nothing.

Notes: expired() may be faster than use_count().

lock

shared_ptr<T> lock() const;

Returns: expired()? shared_ptr<T>(): shared_ptr<T>(*this).

Throws: nothing.

reset

void reset();

Effects: Equivalent to weak_ptr().swap(*this).

swap

void swap(weak_ptr & b);

Effects: Exchanges the contents of the two smart pointers.

Throws: nothing.

Free Functions

comparison

template<class T, class U>
  bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b);

Returns: an unspecified value such that

Throws: nothing.

Notes: Allows weak_ptr objects to be used as keys in associative containers.

swap

template<class T>
  void swap(weak_ptr<T> & a, weak_ptr<T> & b)

Effects: Equivalent to a.swap(b).

Throws: nothing.

Notes: Matches the interface of std::swap. Provided as an aid to generic programming.

Frequently Asked Questions

Q. Can an object create a weak_ptr to itself in its constructor?

A. No. A weak_ptr can only be created from a shared_ptr, and at object construction time no shared_ptr to the object exists yet. Even if you could create a temporary shared_ptr to this, it would go out of scope at the end of the constructor, and all weak_ptr instances would instantly expire.

The solution is to make the constructor private, and supply a factory function that returns a shared_ptr:

class X
{
private:

    X();

public:

    static shared_ptr<X> create()
    {
        shared_ptr<X> px(new X);
        // create weak pointers from px here
        return px;
    }
};

$Date$

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version 1.0. See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.