weak_ptr

# 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

> - operator< is a strict weak ordering as described in section 25.3 `[lib.alg.sorting]` of the C++ standard;
> - under the equivalence relation defined by operator<, `!(a < b) && !(b < a)`, two weak_ptr instances are equivalent if and only if they share ownership or are both empty.

> 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: 2005/07/18 20:33:59 $

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. Copyright 2002-2005 Peter Dimov. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose.