# Class shared_array

Class shared_array stores a pointer to a dynamically allocated array. (Dynamically allocated arrays are allocated with the C++ `new[]` expression.) The array pointed to is guaranteed to be deleted, either on destruction of the shared_array, on shared_array::operator=(), or via an explicit shared_array::reset(). See example.

Class shared_array meets the CopyConstuctible and Assignable requirements of the C++ Standard Library, and so can be used in C++ Standard Library containers. A specialization of std:: less< > for boost::shared_ptr<Y> is supplied so that shared_array works by default for Standard Library's Associative Container Compare template parameter. For compilers not supporting partial specialization, the user must explicitly pass the less<> functor.

Class shared_array cannot correctly hold a pointer to a single object. See shared_ptr for that usage.

Class shared_array will not work correctly with cyclic data structures. For example, if main() holds a shared_array pointing to array A, which directly or indirectly holds a shared_array pointing back to array A, then array A's use_count() will be 2, and destruction of the main() shared_array will leave array A dangling with a use_count() of 1.

A C++ Standard Library vector is a heavier duty alternative to a shared_array.

The class is a template parameterized on `T`, the type of the object pointed to. `T` must meet the smart pointer Common requirements.

## Class shared_array Synopsis

    #include <boost/smart_ptr.hpp>
    namespace boost {

    template<typename T> class shared_array {

     public:
       typedef T element_type;

       explicit shared_array( T* p=0 );
       shared_array( const shared_array& );  // never throws
       ~shared_array();

       shared_array& operator=( const shared_array& );  // never throws

       void reset( T* p=0 );

       T& operator[](std::size_t i) const;  // never throws
       T* get() const;  // never throws

       long use_count() const;  // never throws
       bool unique() const;  // never throws

       void swap( shared_array<T>& other ) throw()
       };

    template<typename T>
      inline bool operator==(const shared_array<T>& a, const shared_array<T>& b)
        { return a.get() == b.get(); }

    template<typename T>
      inline bool operator!=(const shared_array<T>& a, const shared_array<T>& b)
        { return a.get() != b.get(); }
    }

    namespace std {

    template<typename T>
      inline void swap(boost::shared_array<T>& a, boost::shared_array<T>& b)
        { a.swap(b); }

    template<typename T>
      struct less< boost::shared_array<T> >
        : binary_function<boost::shared_array<T>, boost::shared_array<T>, bool>
      {
        bool operator()(const boost::shared_array<T>& a,
            const boost::shared_array<T>& b) const
          { return less<T*>()(a.get(),b.get()); }
      };

    } // namespace std

Specialization of std::swap uses the fast, non-throwing swap that's provided as a member function instead of using the default algorithm which creates a temporary and uses assignment.
Specialization of std::less allows use of shared arrays as keys in C++ Standard Library associative collections.
The std::less specializations use std::less<T*> to perform the comparison. This insures that pointers are handled correctly, since the standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel] paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons] paragraph 8).
It's still a controversial question whether supplying only std::less is better than supplying a full range of comparison operators (<, >, <=, >=).

The current implementation does not supply the specializations if the macro name BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION is defined.

## Class shared_array Members

### shared_array element_type

    typedef T element_type;

Provides the type of the stored pointer.

### shared_array constructors

    explicit shared_array( T* p=0 );

Constructs a shared_array, storing a copy of `p`, which must have been allocated via a C++ `new`[] expression or be 0. Afterwards, use_count() is 1 (even if p==0; see ~shared_array).

The only exception which may be thrown is `std::bad_alloc`. If an exception is thrown, `delete[] p` is called.

    shared_array( const shared_array& r);  // never throws

Constructs a shared_array, as if by storing a copy of the pointer stored in r. Afterwards, use_count() for all copies is 1 more than the initial r.use_count().

### shared_array destructor

    ~shared_array();

If use_count() == 1, deletes the array pointed to by the stored pointer. Otherwise, use_count() for any remaining copies is decremented by 1. Note that in C++ `delete`[] on a pointer with a value of 0 is harmless.

Does not throw exceptions.

### shared_array operator=

    shared_array& operator=( const shared_array& r);  // never throws

First, if use_count() == 1, deletes the array pointed to by the stored pointer. Otherwise, use_count() for any remaining copies is decremented by 1. Note that in C++ `delete`[] on a pointer with a value of 0 is harmless.

Then replaces the contents of this, as if by storing a copy of the pointer stored in r. Afterwards, use_count() for all copies is 1 more than the initial r.use_count().

### shared_array reset

    void reset( T* p=0 );

First, if use_count() == 1, deletes the array pointed to by the stored pointer. Otherwise, use_count() for any remaining copies is decremented by 1. Note that in C++ `delete`[] on a pointer with a value of 0 is harmless.

Then replaces the contents of this, as if by storing a copy of p, which must have been allocated via a C++ `new`[] expression or be 0. Afterwards, use_count() is 1 (even if p==0; see ~shared_array).

The only exception which may be thrown is `std::bad_alloc`. If an exception is thrown, `delete[] p` is called.

### shared_array operator[]

`T& operator[](std::size_t i) const; // never throws`

Returns a reference to element `i` of the array pointed to by the stored pointer.

Behavior is undefined (and almost certainly undesirable) if `get()==0`, or if `i` is less than 0 or is greater or equal to the number of elements in the array.

### shared_array get

    T* get() const;  // never throws

T is not required be a complete type. See Common Requirements.

Returns the stored pointer.

### shared_array use_count

`long use_count() const; // never throws`

T is not required be a complete type. See Common Requirements.

Returns the number of shared_arrays sharing ownership of the stored pointer.

### shared_array unique

`bool unique() const; // never throws`

T is not required be a complete type. See Common Requirements.

Returns use_count() == 1.

### shared_array swap

`void swap( shared_array<T>& other ) throw()`

T is not required be a complete type. See Common Requirements.

Swaps the two smart pointers, as if by std::swap.

## Class shared_array example

[To be supplied. In the meantime, see smart_ptr_test.cpp.]

Revised 24 May, 2001

© Copyright Greg Colvin and Beman Dawes 1999. 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.