2017-01-18 4 views
4

В this ответ T.C. состоянияЧто такое 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? Кажется, что они создают массив размера int 30.

ответ

2

Пример не такой уж большой. По массив неизвестного размера они предположительно означает, что он может быть вызван следующим образом:

int arr2_size = 30; 
boost::shared_ptr<int[]> sh_arr2 = boost::make_shared<int[]>(arr2_size); 

Поскольку arr2_size может динамически определить его можно считать «неизвестно».

Во-вторых, они создают массив размером 30, но sh_arr3 содержит размер в самом типе, который позволит компилятору выдавать предупреждения, если доступ выходит за пределы. Тип без явного размера не сможет обнаружить эти случаи.

1

Во-первых, как make_shared поддерживает тип массива неизвестного размера? I подумает, что размер массива не требуется.

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? Оба кажутся для создания массива размера int 30.

Вторая включает в себя проверку диапазона. Из Boost docs:

Начиная с выпуском Boost, 1.53, shared_ptr может быть использован для проведения указателя на динамически выделенный массив. Это выполняется с использованием типа массива (T [] или T [N]) в качестве параметра шаблона. Существует практически никакой разницы между использованием несеризованного массива, T [] и размером , T [N]; последний просто позволяет оператору [] выполнить диапазон проверить индекс.