4.6.0
Freundlich's C++ toolkit
|
unique_ptr, shared_ptr and weak_ptr without default constructors.
A smart pointer is a class that takes ownership over a pointer, freeing the object pointed to when the smart pointer is destroyed. Such a smart pointer resides on the stack, so freeing is done automatically.
fcppt provides all smart pointers that are also in C++11 with the following changes:
fcppt provides three smart pointer classes, each with their own trade-offs.
Class name | Description |
---|---|
A move-only smart pointer that is the unique owner of an object. This should be the default choice of smart pointer. | |
Manages objects using a shared count. Every shared ptr pointing to the same object increases the shared count by one. The object will only be destroyed when all shared ptrs have been destroyed. | |
A weak reference to an object managed by shared ptrs. This smart pointer doesn't contribute to the shared count and can be used to observe if shared ptrs are still alive. |
Multiple fcppt::shared_ptr that point to the same object share ownership by internally managing a shared count that counts how many shared ptrs are left. This shared count will be increased whenever a shared ptr is copied and decreased when one is destroyed.
For most use cases, unique ptrs should be preferred over shared ptrs.
The general traits of a shared ptr are as follows:
Copying, destroying and assigning of shared ptrs is thread-safe. This usually means that these atomic operations are involved, making the operations a lot less cheap than they might seem.
Although the shared ptr gets its deleter as a template parameter, it does type erasure on it. This implies that the owned object does not have to be complete unless the shared ptr is constructed or dereferenced.
Because not only the shared count but also the owned object must be dynamically allocated, it is possible to put them both into the same memory block if the deleter is the default one that uses delete
. This is done by fcppt::make_shared_ptr.
An fcppt::weak_ptr can be used to keep track of the shared ptrs to one object without contributing to the shared count. This way it is possible to observe if shared ptrs are still alive.
Casting shared pointers must be done through special functions, so that the shared count between them is preserved.
Here is a simple example using shared pointers.
fcppt::make_shared_ptr can be used to place an object allocated via new into the same memory block as the shared count managed by the shared ptrs. Another reason to use this function is to avoid memory leaks, that can happen due to C++'s unspecified order of evaluation, if you are not careful.
Here is an example of how not using fcppt::make_shared_ptr can lead to a memory leak.
Using fcppt::make_shared_ptr eliminates this problem and also makes the dynamic memory management of the shared ptrs more efficient.
A weak pointer can be used to keep track of the shared ptrs to one object without contributing to the shared count. We can then observe if a shared ptr is still alive. This can also be used to break cycles.
A weak ptr can be used as follows:
When casting shared ptrs, using static_cast
, dynamic_cast
or const_cast
directly will not work, because the shared count will not be preserved. Instead, we have to use one of the special functions fcppt::static_pointer_cast, fcppt::dynamic_pointer_cast or fcppt::const_pointer_cast.
Here is an example:
In contrast to a shared ptr, a unique ptr always is the sole owner of an object.
The general traits of a unique ptr are as follows:
Unique ptrs cannot be copied or assigned. Instead, they must be moved, which takes the ownership away from the original owner. This also means that the moved-from object will become the null pointer, so it should not be dereferenced.
Unique ptrs don't use type erasure for their deleter. This means that when constructing, copying, assigning, destroying or dereferencing unique ptrs, the type of the pointed to object must usually be complete (this depends on the deleter used).
fcppt::make_unique_ptr should be used to construct unique ptrs. It is similar to fcppt::make_shared_ptr in the sense that it helps to avoid memory leaks, but it is not more efficient than normal construction of unique ptrs, because there is no shared count to keep track of.
The first thing to note is that unique ptrs are an excellent candidate for factory functions. They don't impose overly strict ownership requirements like shared ptr does. However, unique ptrs can be converted into shared ptrs as desired. The following example shows how such a factory can be created.
The return of make_unique_ptr
doesn't require a move, because it returns an rvalue.
The factory can be used as follows:
Again, there is no move required because the factory also returns an rvalue.
The next example shows when a move is required. This is generally true when an lvalue is involved (which means a named object here). The reason for this is to ensure that a unique ptr doesn't accidentally get its object disowned.
Consider the following example where an implicit move would be very dangerous:
Unique pointers are not implicitly convertible to any other unique pointers. To convert a unique pointer to a unique pointer to base, use fcppt::unique_ptr_to_base.
Similarly, fcppt::unique_ptr_to_const must be used to obtain a unique pointer to a const object.
fcppt used to provide a scoped_ptr class similar to boost::scoped_ptr
that additionally took a deleter. This class has been removed in favor of const unique ptrs.
A unique ptr that has been declared const cannot be copied nor moved. Additionally, it can also not be swapped.
A unique ptr can also be used to implement the pimpl idiom. When a unique ptr object is defined, the pointed to object doesn't need to be complete. It only has to be complete when the destructor of the unique ptr is instantiated. Therefore, an implementation can be hidden by using unique ptrs as shown in the following example:
Because foo
has an explicitly declared destructor, the destruction of the implementation can be hidden in a source file.
As previously mentioned, fcppt's smart pointers all take the deleter as a template parameter in order to ensure maximum type safety. Such a deleter must have the following properties:
For some smart pointer over type Type
the deleter must be callable with an expression of type Type *
. The deleter must ensure to destroy the object if it is not a null pointer.
fcppt predefines several deleters:
For some invented variable name ptr
of type Type *
their semantics are as follows:
fcppt::default_deleter | delete ptr; |
fcppt::c_deleter | std::free(ptr); |
fcppt::com_deleter | if(ptr) ptr->Release(); |
The following example shows how fcppt::c_deleter can be used to free memory allocated via std::malloc
Header file | Description |
---|---|
c_deleter.hpp | Contains fcppt::c_deleter. |
com_deleter.hpp | Contains fcppt::com_deleter. |
const_pointer_cast.hpp | Contains fcppt::const_pointer_cast. |
default_deleter.hpp | Contains fcppt::default_deleter. |
dynamic_pointer_cast.hpp | Contains fcppt::dynamic_pointer_cast. |
make_shared_ptr.hpp | Contains fcppt::make_shared_ptr. |
make_unique_ptr.hpp | Contains fcppt::make_unique_ptr. |
shared_ptr_fwd.hpp | Contains fcppt::shared_ptr's declaration. |
shared_ptr_decl.hpp | Contains fcppt::shared_ptr's definition. |
shared_ptr_impl.hpp | Contains the definition of fcppt::shared_ptr's member functions. |
shared_ptr.hpp | The same as shared_ptr_impl.hpp |
static_pointer_cast.hpp | Contains fcppt::static_pointer_cast |
unique_ptr_fwd.hpp | Contains fcppt::unique_ptr's declaration. |
unique_ptr_decl.hpp | Contains fcppt::unique_ptr's definition. |
unique_ptr_impl.hpp | Contains the definition of fcppt::unique_ptr's member functions. |
unique_ptr.hpp | The same as unique_ptr_impl.hpp |
unique_ptr_to_base.hpp | Contains fcppt::unique_ptr_to_base. |
unique_ptr_to_const.hpp | Contains fcppt::unique_ptr_to_const. |
weak_ptr_fwd.hpp | Contains fcppt::weak_ptr's declaration. |
weak_ptr_decl.hpp | Contains fcppt::weak_ptr's definition. |
weak_ptr_impl.hpp | Contains the definition of fcppt::weak_ptr's member functions. |
weak_ptr.hpp | The same as weak_ptr_impl.hpp |
Classes | |
struct | fcppt::c_deleter |
A deleter that uses std::free to destroy an object. More... | |
struct | fcppt::com_deleter |
A deleter that uses the Release member function to destroy an object. More... | |
struct | fcppt::default_deleter |
A deleter that uses delete to destroy an object. More... | |
class | fcppt::enable_shared_from_this< Type > |
Allows an object to obtain a shared ptr to itself. More... | |
struct | fcppt::is_unique_ptr< Type > |
Tests if a type is an fcppt::unique_ptr. More... | |
class | fcppt::shared_ptr< Type, Deleter > |
A shared pointer class that gets the deleter as a template parameter. More... | |
struct | fcppt::shared_ptr_hash< fcppt::shared_ptr< Type > > |
A hash for fcppt::shared_ptr that hashes pointers. More... | |
class | fcppt::unique_ptr< Type, Deleter > |
A simpler unique_ptr that shouldn't be used as a null pointer. More... | |
class | fcppt::weak_ptr< Type, Deleter > |
A weak reference to an object owned by a shared pointer. More... | |
Functions | |
template<typename Dest , typename Source > | |
fcppt::shared_ptr< Dest > | fcppt::const_pointer_cast (fcppt::shared_ptr< Source const > const &_ptr) |
Casts an fcppt::shared_ptr using const_cast | |
template<typename Dest , typename Source > | |
fcppt::optional::object< fcppt::shared_ptr< Dest > > | fcppt::dynamic_pointer_cast (fcppt::shared_ptr< Source > const &_ptr) |
Casts an fcppt::shared_ptr using dynamic_cast | |
template<typename Res , typename... Args> | |
fcppt::shared_ptr< Res > | fcppt::make_shared_ptr (Args &&..._args) |
Like std::make_shared but for fcppt::shared_ptr. | |
template<typename Res , typename... Args> | |
fcppt::unique_ptr< Res > | fcppt::make_unique_ptr (Args &&..._args) |
Like std::make_unique for fcppt::unique_ptr. | |
template<typename Type1 , typename Type2 , typename Deleter > | |
bool | fcppt::operator== (fcppt::shared_ptr< Type1, Deleter > const &left, fcppt::shared_ptr< Type2, Deleter > const &right) |
Compares two shared ptrs for equality. | |
template<typename Type1 , typename Type2 , typename Deleter > | |
bool | fcppt::operator!= (fcppt::shared_ptr< Type1, Deleter > const &left, fcppt::shared_ptr< Type2, Deleter > const &right) |
Compares two shared ptrs for inequality. | |
template<typename Type1 , typename Type2 , typename Deleter > | |
bool | fcppt::operator< (fcppt::shared_ptr< Type1, Deleter > const &left, fcppt::shared_ptr< Type2, Deleter > const &right) |
Checks if one shared ptr is less than the other. | |
template<typename Type , typename Deleter > | |
void | fcppt::swap (fcppt::shared_ptr< Type, Deleter > &left, fcppt::shared_ptr< Type, Deleter > &right) noexcept |
Swaps two shared pointers. | |
template<typename Ch , typename Traits , typename Type , typename Deleter > | |
std::basic_ostream< Ch, Traits > & | fcppt::operator<< (std::basic_ostream< Ch, Traits > &_stream, fcppt::shared_ptr< Type, Deleter > const &_ptr) |
Outputs a shared pointer. | |
template<typename Dest , typename Source > | |
fcppt::shared_ptr< Dest > | fcppt::static_pointer_cast (fcppt::shared_ptr< Source > const &_ptr) |
Casts an fcppt::shared_ptr using static_cast | |
template<typename Cast , typename Derived , typename Base , typename Deleter > | |
fcppt::variant::object< fcppt::unique_ptr< Derived, Deleter >, fcppt::unique_ptr< Base, Deleter > > | fcppt::unique_ptr_dynamic_cast (fcppt::unique_ptr< Base, Deleter > &&_other) noexcept |
Casts a unique_ptr to a derived class. | |
template<typename Type > | |
fcppt::optional::object< fcppt::unique_ptr< Type > > | fcppt::unique_ptr_from_std (std::unique_ptr< Type > &&_ptr) |
Converts a std::unique_ptr to an fcppt unique ptr. | |
template<typename Base , typename Derived , typename Deleter > | |
fcppt::unique_ptr< Base, Deleter > | fcppt::unique_ptr_to_base (fcppt::unique_ptr< Derived, Deleter > &&_other) noexcept |
Casts a unique_ptr to a base class. | |
template<typename Type , typename Deleter > | |
fcppt::unique_ptr< Type const, Deleter > | fcppt::unique_ptr_to_const (fcppt::unique_ptr< Type, Deleter > &&_other) noexcept |
Casts a unique_ptr to a const unique_ptr. | |
template<typename Type1 , typename Type2 , typename Deleter > | |
bool | fcppt::operator< (fcppt::weak_ptr< Type1, Deleter > const &left, fcppt::weak_ptr< Type2, Deleter > const &right) noexcept |
Checks if one weak ptr is less than the other. | |
template<typename Type , typename Deleter > | |
void | fcppt::swap (fcppt::weak_ptr< Type, Deleter > &left, fcppt::weak_ptr< Type, Deleter > &right) noexcept |
Swaps two weak pointers. | |
fcppt::shared_ptr< Dest > fcppt::const_pointer_cast | ( | fcppt::shared_ptr< Source const > const & | _ptr | ) |
Casts an fcppt::shared_ptr using const_cast
Casts the pointer stored in _ptr to type U *
using const_cast
.
Dest | The type of the destination shared_ptr |
Source | The type of the source shared_ptr |
_ptr | The source shared_ptr |
fcppt::optional::object< fcppt::shared_ptr< Dest > > fcppt::dynamic_pointer_cast | ( | fcppt::shared_ptr< Source > const & | _ptr | ) |
Casts an fcppt::shared_ptr using dynamic_cast
Casts the pointer stored in _ptr to type U *
using dynamic_cast
. This means that T *
and U
must be members of the same class hierarchy. If the cast succeeds, the resulting shared_ptr will share ownership with the source.
Dest | The type of the destination shared_ptr |
Source | The type of the source shared_ptr |
_ptr | The source shared_ptr |
|
inline |
Like std::make_shared
but for fcppt::shared_ptr.
|
inline |
Like std::make_unique
for fcppt::unique_ptr.
bool fcppt::operator!= | ( | fcppt::shared_ptr< Type1, Deleter > const & | left, |
fcppt::shared_ptr< Type2, Deleter > const & | right ) |
Compares two shared ptrs for inequality.
Compares left and right for inequality, comparing their pointers. Pointers to Type1 and to Type2 must be inequality comparable.
left | The left argument |
right | The right argument |
bool fcppt::operator< | ( | fcppt::shared_ptr< Type1, Deleter > const & | left, |
fcppt::shared_ptr< Type2, Deleter > const & | right ) |
Checks if one shared ptr is less than the other.
Checks if left is less than right, comparing their pointers with std::less
.
Pointers to Type1 and to Type2 must be comparable using std::less
.
left | The left argument |
right | The right argument |
|
noexcept |
Checks if one weak ptr is less than the other.
Checks if left is less than right, comparing their pointers with std::less
.
Pointers to Type1 and to Type2 must be comparable using std::less
.
left | The left argument |
right | The right argument |
|
inline |
Outputs a shared pointer.
Outputs _ptr to _stream.
bool fcppt::operator== | ( | fcppt::shared_ptr< Type1, Deleter > const & | left, |
fcppt::shared_ptr< Type2, Deleter > const & | right ) |
Compares two shared ptrs for equality.
Compares left and right for equality, comparing their pointers. Pointers to Type1 and to Type2 must be equality comparable.
left | The left argument |
right | The right argument |
fcppt::shared_ptr< Dest > fcppt::static_pointer_cast | ( | fcppt::shared_ptr< Source > const & | _ptr | ) |
Casts an fcppt::shared_ptr using static_cast
Casts the pointer stored in _ptr to type U *
using static_cast
.
Dest | The type of the destination shared_ptr |
Source | The type of the source shared_ptr |
_ptr | The source shared_ptr |
static_cast
is not well formed.
|
noexcept |
Swaps two shared pointers.
Swaps left and right
left | The left argument |
right | The right argument |
|
noexcept |
Swaps two weak pointers.
Swaps left and right
left | The left argument |
right | The right argument |
|
inlinenoexcept |
Casts a unique_ptr to a derived class.
Tries to cast the given unique ptr to Derived using the cast function Cast. The result is either a unique_ptr of type Derived, or (if the cast fails) of type Base.
Cast | A cast function from fcppt.casts |
fcppt::optional::object< fcppt::unique_ptr< Type > > fcppt::unique_ptr_from_std | ( | std::unique_ptr< Type > && | _ptr | ) |
Converts a std::unique_ptr
to an fcppt unique ptr.
|
inlinenoexcept |
Casts a unique_ptr to a base class.
|
inlinenoexcept |
Casts a unique_ptr to a const unique_ptr.