...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
Introduction
Synopsis
Free Functions
Example
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.
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 }
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)... )
, wherepv
is avoid*
pointing to storage suitable to hold an object of typeT
, 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 expressionnew( pv ) T()
ornew( pv ) T( std::forward<Args>(args)... )
.allocate_shared
uses a copy ofa
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 typeT
.Postconditions:
get() != 0 && use_count() == 1
.Throws:
bad_alloc
, or an exception thrown fromA::allocate
or the constructor ofT
.Notes: This implementation allocates the memory required for the returned
shared_ptr
and an object of typeT
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 ofT
.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 ofT
, you may do so by wrapping the parameter in a call toboost::ref
. In addition, you will be limited to a maximum of 9 arguments (not counting the allocator argument of allocate_shared).
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.