Ответ 1
По умолчанию shared_ptr
будет вызывать delete
на управляемом объекте, если к нему не останется больше ссылок. Однако при распределении с помощью new[]
вам нужно вызвать delete[]
, а не delete
, чтобы освободить ресурс.
Чтобы правильно использовать shared_ptr
с массивом, вы должны указать пользовательский отладчик.
template< typename T >
struct array_deleter
{
void operator ()( T const * p)
{
delete[] p;
}
};
Создайте shared_ptr следующим образом:
std::shared_ptr<int> sp( new int[10], array_deleter<int>() );
Теперь shared_ptr
будет правильно вызывать delete[]
при уничтожении управляемого объекта.
Как показано в комментариях, с С++ 11 вы можете использовать std::default_delete
частичную специализацию для типов массивов вместо array_deleter
выше.
std::shared_ptr<int> sp( new int[10], std::default_delete<int[]>() );
Вы также можете использовать выражение лямбда вместо функторов.
std::shared_ptr<int> sp( new int[10], []( int *p ) { delete[] p; } );
Кроме того, если вам действительно не нужен общий доступ к управляемому объекту, unique_ptr
лучше подходит для этой задачи, поскольку он имеет частичную специализацию для типов массивов.
std::unique_ptr<int[]> up( new int[10] ); // this will correctly call delete[]
Изменения, внесенные расширениями С++ для фундаментальных основ библиотеки
shared_ptr
дополняется Технической спецификацией основных средств библиотеки (TS), чтобы позволить ей работать из коробки для случаев, когда ей принадлежит массив объектов; нет необходимости явно указывать дебетер. Текущая черновик изменений shared_ptr
, установленных для этого TS, можно найти в N4082. Эти изменения будут доступны через пространство имен std::experimental
и включены в заголовок <experimental/memory>
. Некоторые из соответствующих изменений для поддержки shared_ptr
для массивов:
— Определение типа члена element_type
изменяет
typedef T element_type;typedef typename remove_extent<T>::type element_type;
— Добавляется член operator[]
element_type& operator[](ptrdiff_t i) const noexcept;
— В отличие от частичной специализации unique_ptr
для массивов, как shared_ptr<T[]>
, так и shared_ptr<T[N]>
будут действительны, и оба они приведут к вызову delete[]
в управляемом массиве объектов.
template<class Y> explicit shared_ptr(Y* p);
Требуется:
Y
должен быть полный тип. Выражениеdelete[] p
, когдаT
является типом массива, илиdelete p
, когдаT
не является типом массива, должно быть хорошо сформировано, должно иметь четко определенное поведение и не должно генерировать исключения. ЕслиT
U[N]
,Y(*)[N]
должен быть конвертирован вT*
; когдаT
U[]
,Y(*)[]
должен быть конвертирован вT*
; в противном случаеY*
должен быть конвертирован вT*
.