An object referenced by the contained raw pointer will not be destroyed until reference count is greater than zero i.e. until all copies of shared_ptr have been deleted. So, we should use shared_ptr when we want to assign one raw pointer to multiple owners. // referring to the same managed object.
I am of the opinion that shared_ptr should only be used when there is explicit transfer or sharing of ownership, which I think is quite rare outside of cases where a function allocates some memory, populates it with some data, and returns it, and there is understanding between the caller and the callee that the former ...
Use unique_ptr when you want a single pointer to an object that will be reclaimed when that single pointer is destroyed. Use shared_ptr when you want multiple pointers to the same resource.
So no, you shouldn't. The purpose of shared_ptr is to manage an object that no one "person" has the right or responsibility to delete, because there could be others sharing ownership. So you shouldn't ever want to, either.
With C++17, shared_ptr
can be used to manage a dynamically allocated array. The shared_ptr
template argument in this case must be T[N]
or T[]
. So you may write
shared_ptr<int[]> sp(new int[10]);
From n4659, [util.smartptr.shared.const]
template<class Y> explicit shared_ptr(Y* p);
Requires:
Y
shall be a complete type. The expressiondelete[] p
, whenT
is an array type, ordelete p
, whenT
is not an array type, shall have well-defined behavior, and shall not throw exceptions.
...
Remarks: WhenT
is an array type, this constructor shall not participate in overload resolution unless the expressiondelete[] p
is well-formed and eitherT
isU[N]
andY(*)[N]
is convertible toT*
, orT
isU[]
andY(*)[]
is convertible toT*
. ...
To support this, the member type element_type
is now defined as
using element_type = remove_extent_t<T>;
Array elements can be access using operator[]
element_type& operator[](ptrdiff_t i) const;
Requires:
get() != 0 && i >= 0
. IfT
isU[N]
,i < N
. ...
Remarks: WhenT
is not an array type, it is unspecified whether this member function is declared. If it is declared, it is unspecified what its return type is, except that the declaration (although not necessarily the definition) of the function shall be well formed.
Prior to C++17, shared_ptr
could not be used to manage dynamically allocated arrays. By default, shared_ptr
will call delete
on the managed object when no more references remain to it. However, when you allocate using new[]
you need to call delete[]
, and not delete
, to free the resource.
In order to correctly use shared_ptr
with an array, you must supply a custom deleter.
template< typename T >
struct array_deleter
{
void operator ()( T const * p)
{
delete[] p;
}
};
Create the shared_ptr as follows:
std::shared_ptr<int> sp(new int[10], array_deleter<int>());
Now shared_ptr
will correctly call delete[]
when destroying the managed object.
The custom deleter above may be replaced by
the std::default_delete
partial specialization for array types
std::shared_ptr<int> sp(new int[10], std::default_delete<int[]>());
a lambda expression
std::shared_ptr<int> sp(new int[10], [](int *p) { delete[] p; });
Also, unless you actually need share onwership of the managed object, a unique_ptr
is better suited for this task, since it has a partial specialization for array types.
std::unique_ptr<int[]> up(new int[10]); // this will correctly call delete[]
Another pre-C++17 alternative to the ones listed above was provided by the Library Fundamentals Technical Specification, which augmented shared_ptr
to allow it to work out of the box for the cases when it owns an array of objects. The current draft of the shared_ptr
changes slated for this TS can be found in N4082. These changes will be accessible via the std::experimental
namespace, and included in the <experimental/memory>
header. A few of the relevant changes to support shared_ptr
for arrays are:
— The definition of the member type element_type
changes
typedef T element_type;typedef typename remove_extent<T>::type element_type;
— Member operator[]
is being added
element_type& operator[](ptrdiff_t i) const noexcept;
— Unlike the unique_ptr
partial specialization for arrays, both shared_ptr<T[]>
and shared_ptr<T[N]>
will be valid and both will result in delete[]
being called on the managed array of objects.
template<class Y> explicit shared_ptr(Y* p);
Requires:
Y
shall be a complete type. The expressiondelete[] p
, whenT
is an array type, ordelete p
, whenT
is not an array type, shall be well-formed, shall have well defined behavior, and shall not throw exceptions. WhenT
isU[N]
,Y(*)[N]
shall be convertible toT*
; whenT
isU[]
,Y(*)[]
shall be convertible toT*
; otherwise,Y*
shall be convertible toT*
.
A possibly easier alternative that you might be able to use is shared_ptr<vector<int>>
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With