use smart pointer to manage a dynamically allocated array in cpp
c++ - Can you make a std::shared_ptr manage an array allocated with new T[]? - Stack Overflow:
https://stackoverflow.com/questions/13061979/can-you-make-a-stdshared-ptr-manage-an-array-allocated-with-new-t
c++ - What is the difference between shared_ptr
https://stackoverflow.com/questions/75224318/what-is-the-difference-between-shared-ptrint-and-shared-ptrint
short answer
std::shared_ptr<int> sp(new int[10], [](int *p) { delete[] p; });
long answer
part 1
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:
Yshall be a complete type. The expressiondelete[] p, whenTis an array type, ordelete p, whenTis not an array type, shall have well-defined behavior, and shall not throw exceptions.
...
Remarks: WhenTis an array type, this constructor shall not participate in overload resolution unless the expressiondelete[] pis well-formed and eitherTisU[N]andY(*)[N]is convertible toT*, orTisU[]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. IfTisU[N],i < N. ...
Remarks: WhenTis 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_deletepartial specialization for array typesstd::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[]
Changes introduced by the C++ Extensions for Library Fundamentals
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:
Yshall be a complete type. The expressiondelete[] p, whenTis an array type, ordelete p, whenTis not an array type, shall be well-formed, shall have well defined behavior, and shall not throw exceptions. WhenTisU[N],Y(*)[N]shall be convertible toT*; whenTisU[],Y(*)[]shall be convertible toT*; otherwise,Y*shall be convertible toT*.
part 2
shared_ptr<int> holds an int* pointer to a single int. That int is expected to be allocated with the new operator (preferably via a call to std::make_shared<int>(value)), and will be freed with the delete operator.
shared_ptr<int[]> holds an int* pointer to the 1st element of an int[] array. That array is expected to be allocated with the new[] operator (preferably via a call to std::make_shared<int[]>(size)), and will be freed with the delete[] operator.
                    
                
                
            
        
浙公网安备 33010602011771号