Что такое make_shared неизвестного размера?
В этом ответе ТС заявляет
boost::make_shared
и т. д. поддерживают типы массивов - либо с неизвестным размером, либо с фиксированным размером
boost::shared_ptr<int[]> sh_arr2 = boost::make_shared<int[]>(30);
boost::shared_ptr<int[30]> sh_arr3 = boost::make_shared<int[30]>();
Во-первых, как make_shared может поддерживать тип массива неизвестного размера? Я думаю, размер массива обязателен.
Во-вторых, в чем разница между sh_arr2 и sh_arr3? Кажется, что оба создают массив размером 30.
2 ответа
Пример не так уж велик. Под массивом неизвестного размера они предположительно подразумевают, что он может быть вызван следующим образом:
int arr2_size = 30;
boost::shared_ptr<int[]> sh_arr2 = boost::make_shared<int[]>(arr2_size);
поскольку arr2_size
может быть определено динамически, его можно считать "неизвестным".
Во-вторых, они оба создают массив размером 30, но sh_arr3
содержит размер в самом типе, который позволит компилятору выдавать предупреждения, если доступ выходит за пределы. Тип без явного размера не сможет обнаружить эти случаи.
Во-первых, как make_shared может поддерживать тип массива неизвестного размера? Я думаю, размер массива обязателен.
Boost использует вспомогательный класс для определения типа возвращаемого значения shared_ptr::operator[](...)
, Он также использует другой вспомогательный класс boost::detail::sp_extent
который обеспечивает специализации для типов массивов для определения границ (если T
может быть разложен на T[]
) Вот краткий фрагмент из http://www.boost.org/doc/libs/1_63_0/boost/smart_ptr/shared_ptr.hpp:
namespace boost{
template<typename T>
class shared_ptr{
.....
typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const
{
BOOST_ASSERT( px != 0 );
BOOST_ASSERT( i >= 0 && ( i < boost::detail::sp_extent< T >::value || boost::detail::sp_extent< T >::value == 0 ) );
return static_cast< typename boost::detail::sp_array_access< T >::type >( px[ i ] );
}
....
}
namespace detail{
template< class T > struct sp_array_access
{ typedef void type; };
template< class T > struct sp_array_access< T[] >
{ typedef T & type; };
template< class T, std::size_t N > struct sp_array_access< T[N] >
{ typedef T & type; };
template< class T > struct sp_extent
{ enum _vt { value = 0 }; };
template< class T, std::size_t N > struct sp_extent< T[N] >
{ enum _vt { value = N }; };
}//end namepace detail
}//end namespace boost
Во-вторых, в чем разница между sh_arr2 и sh_arr3? Кажется, что оба создают массив размером 30.
Второй включает проверку диапазона. Из Boost Docs:
Начиная с Boost версии 1.53, shared_ptr может использоваться для хранения указателя на динамически размещенный массив. Это достигается путем использования типа массива (T[] или T[N]) в качестве параметра шаблона. Почти нет разницы между использованием массива без размера T [] и массива с размерами T[N]; последнее позволяет оператору [] выполнять проверку диапазона индекса.