boost.png (6897 bytes)make_shared and allocate_shared for arrays

Introduction
Synopsis
Free Functions
Examples
History
References

Introduction

Originally the Boost function templates make_shared and allocate_shared were for efficient allocation of shared objects only. There was a need to have efficient allocation of shared arrays. One criticism of class template shared_array was always the lack of a make_shared utility which ensures only a single allocation.

The header files <boost/smart_ptr/make_shared_array.hpp> and <boost/smart_ptr/allocate_shared_array.hpp> provide function templates, overloads of make_shared and allocate_shared for array types, to address this need. make_shared uses the global operator new to allocate memory, whereas allocate_shared uses an user-supplied allocator, allowing finer control.

Synopsis

namespace boost {
    template<typename U> // U is T[]
    shared_ptr<U> make_shared(size_t size);

    template<typename U, typename A> // U is T[]
    shared_ptr<U> allocate_shared(const A& allocator, size_t size);
    
    template<typename U> // U is T[N]
    shared_ptr<U> make_shared();

    template<typename U, typename A> // U is T[N]
    shared_ptr<U> allocate_shared(const A& allocator);
   
    template<typename U> // U is T[]
    shared_ptr<U> make_shared(size_t size, const T& value);

    template<typename U, typename A> // U is T[]
    shared_ptr<U> allocate_shared(const A& allocator, size_t size, const T& value);

    template<typename U> // U is T[N]
    shared_ptr<U> make_shared(const T& value);

    template<typename U, typename A> // U is T[N]
    shared_ptr<U> allocate_shared(const A& allocator, const T& value);

    template<typename U> // U is T[]
    shared_ptr<U> make_shared_noinit(size_t size);

    template<typename U, typename A> // U is T[]
    shared_ptr<U> allocate_shared_noinit(const A& allocator, size_t size);

    template<typename U> // U is T[N]
    shared_ptr<U> make_shared_noinit();

    template<typename U, typename A> // U is T[N]
    shared_ptr<U> allocate_shared_noinit(const A& allocator);
}

Free Functions

template<typename U> // U is T[]
shared_ptr<U> make_shared(size_t size);

template<typename U, typename A> // U is T[]
shared_ptr<U> allocate_shared(const A& allocator, size_t size);

template<typename U> // U is T[N]
shared_ptr<U> make_shared();

template<typename U, typename A> // U is T[N]
shared_ptr<U> allocate_shared(const A& allocator);

Requires: The expression new(pointer) T(), where pointer is a void* pointing to storage suitable to hold an object of type T, shall be well-formed. A shall be an Allocator, as described in section 20.1.5 (Allocator requirements) of the C++ Standard. The copy constructor and destructor of A shall not throw.

Effects: Allocates memory suitable for an array of type T and size size and constructs an array of objects in it via the placement new expression new(pointer) T(). allocate_shared uses a copy of allocator to allocate memory. If an exception is thrown, has no effect.

Returns: A shared_ptr instance that stores and owns the address of the newly constructed array of type T and size size.

Postconditions: get() != 0 && use_count() == 1.

Throws: bad_alloc, or an exception thrown from A::allocate or the constructor of T.

Notes: This implementation allocates the memory required for the returned shared_ptr and an array of type T of size size in a single allocation. This provides efficiency to equivalent to an intrusive smart pointer.

template<typename U> // U is T[]
shared_ptr<U> make_shared(size_t size, const T& value);

template<typename U, typename A> // U is T[]
shared_ptr<U> allocate_shared(const A& allocator, size_t size, const T& value);

template<typename U> // U is T[N]
shared_ptr<U> make_shared(const T& value);

template<typename U, typename A> // U is T[N]
shared_ptr<U> allocate_shared(const A& allocator, const T& value);

Notes: These overloads initialize array objects with the given value.

template<typename U> // U is T[]
shared_ptr<U> make_shared_noinit(size_t size);

template<typename U, typename A> // U is T[]
shared_ptr<U> allocate_shared_noinit(const A& allocator, size_t size);

template<typename U> // U is T[N]
shared_ptr<U> make_shared_noinit();

template<typename U, typename A> // U is T[N]
shared_ptr<U> allocate_shared_noinit(const A& allocator);

Notes: These overloads do not perform value initialization of array objects.

Examples

The following examples value-initialize objects.

boost::shared_ptr<int[]>     a1  = boost::make_shared<int[]>(size);
boost::shared_ptr<int[8]>    a2  = boost::make_shared<int[8]>();
boost::shared_ptr<int[][2]>  a3  = boost::make_shared<int[][2]>(size);
boost::shared_ptr<int[4][2]> a4  = boost::make_shared<int[4][2]>();

The following examples initialize objects with a given value.

boost::shared_ptr<int[]>     a5  = boost::make_shared<int[]>(size, 1);
boost::shared_ptr<int[8]>    a6  = boost::make_shared<int[8]>(1);
boost::shared_ptr<int[][2]>  a7  = boost::make_shared<int[][2]>(size, {1, 2});
boost::shared_ptr<int[4][2]> a8  = boost::make_shared<int[4][2]>({1, 2});

The following examples default-initialize objects.

boost::shared_ptr<int[]>     a9  = boost::make_shared_noinit<int[]>(size);
boost::shared_ptr<int[8]>    a10 = boost::make_shared_noinit<int[8]>();
boost::shared_ptr<int[][2]>  a11 = boost::make_shared_noinit<int[][2]>(size);
boost::shared_ptr<int[4][2]> a12 = boost::make_shared_noinit<int[4][2]>();

History

January 2014. Glen Fernandes reduced the overloads of make_shared and allocate_shared according to N3870.

November 2012. Glen Fernandes contributed implementations of make_shared and allocate_shared for arrays.

References

N3870, Extending make_shared to Support Arrays, Revision 1, Peter Dimov & Glen Fernandes, January, 2014.


$Date: 2014-01-20 11:10:00 -0800 (Mon, 20 Jan 2014) $

Copyright 2012-2014 Glen Fernandes. 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.