boost.png (6897 bytes)make_shared and allocate_shared function templates

Introduction
Synopsis
Free Functions
Example

Introduction

Consistent use of shared_ptr can eliminate the need to use an explicit delete, but alone it provides no support in avoiding explicit new. There have been repeated requests from users for a factory function that creates an object of a given type and returns a shared_ptr to it. Besides convenience and style, such a function is also exception safe and considerably faster because it can use a single allocation for both the object and its corresponding control block, eliminating a significant portion of shared_ptr's construction overhead. This eliminates one of the major efficiency complaints about shared_ptr.

The header file <boost/make_shared.hpp> provides a family of overloaded function templates, make_shared and allocate_shared, 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.

The rationale for choosing the name make_shared is that the expression make_shared<Widget>() can be read aloud and conveys the intended meaning.

Synopsis

namespace boost {

  template<typename T> class shared_ptr;

  template<typename T>
    shared_ptr<T> make_shared();

  template<typename T, typename A>
    shared_ptr<T> allocate_shared( A const & );

#if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS )	// C++0x prototypes

  template<typename T, typename... Args>
    shared_ptr<T> make_shared( Args && ... args );

  template<typename T, typename A, typename... Args>
    shared_ptr<T> allocate_shared( A const & a, Args && ... args );

#else // no C++0X support

  template<typename T, typename Arg1 >
    shared_ptr<T> make_shared( Arg1 const & arg1 );
  template<typename T, typename Arg1, typename Arg2 >
    shared_ptr<T> make_shared( Arg1 const & arg1, Arg2 const & arg2 );
// ...
  template<typename T, typename Arg1, typename Arg2, ..., typename ArgN >
    shared_ptr<T> make_shared( Arg1 const & arg1, Arg2 const & arg2, ..., ArgN const & argN );

  template<typename T, typename A, typename Arg1 >
    shared_ptr<T> allocate_shared( A const & a, Arg1 const & arg1 );
  template<typename T, typename A, typename Arg1, typename Arg2 >
    shared_ptr<T> allocate_shared( Arg1 const & arg1, Arg2 const & arg2 );
// ...
  template<typename T, typename A, typename Arg1, typename Arg2, ..., typename ArgN >
    shared_ptr<T> allocate_shared( A const & a, Arg1 const & arg1, Arg2 const & arg2, ..., ArgN const & argN );

#endif
}

Free Functions

template<class T, class... Args>
    shared_ptr<T> make_shared( Args && ... args );
template<class T, class A, class... Args>
    shared_ptr<T> allocate_shared( A const & a, Args && ... args );

Requires: The expression new( pv ) T( std::forward<Args>(args)... ), where pv 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 object of type T and constructs an object in it via the placement new expression new( pv ) T() or new( pv ) T( std::forward<Args>(args)... ). allocate_shared uses a copy of a 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 object of type T.

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 object of type T in a single allocation. This provides efficiency equivalent to an intrusive smart pointer.

The prototypes shown above are used if your compiler supports rvalue references and variadic templates. They perfectly forward the args parameters to the constructors of T.

Otherwise, the implementation will fall back on forwarding the arguments to the constructors of T as const references. If you need to pass a non-const reference to a constructor of T, you may do so by wrapping the parameter in a call to boost::ref. In addition, you will be limited to a maximum of 9 arguments (not counting the allocator argument of allocate_shared).

Example

boost::shared_ptr<std::string> x = boost::make_shared<std::string>("hello, world!");
std::cout << *x;

$Date: 2008-05-19 15:42:39 -0400 (Mon, 19 May 2008) $

Copyright 2008 Peter Dimov. Copyright 2008 Frank Mori Hess. 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.