Что такое 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]; последнее позволяет оператору [] выполнять проверку диапазона индекса.

Другие вопросы по тегам