Последнее обновление:2026-10-12
Анализ исходников STL array¶
0. Введение¶
Анализ исходников выполнен для версии gcc4.9.1.
C++ tr1, полное название Technical Report 1, — первое расширение стандартной библиотеки C++. Стандарт C++ c++0x должен был включить его, а также некоторые расширения самого языка. tr1 включает давно ожидаемые умные указатели, регулярные выражения и ряд других средств поддержки обобщённого программирования. На этапе черновика пространством имён новых классов и шаблонов было std::tr1.
1. std::tr1::array¶
Использование:
array в tr1 довольно прост: он имитирует встроенный в язык массив и наделяет его поддержкой итераторов, чтобы, как и другие контейнеры, его можно было использовать с алгоритмами. В array из tr1 нет конструктора и деструктора. Итератор — это просто указатель, определённый через переданный извне тип.
Взглянем кратко на исходники этого статического массива array:
template<typename _Tp, std::size_t _Nm>
struct array
{
typedef _Tp value_type;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef value_type* iterator;
typedef const value_type* const_iterator;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
}
reverse_iterator.
Кажется, что итератор выше один, но на самом деле их два: есть ещё iterator — тоже просто указатель, определённый через переданный извне тип и используемый как итератор.
Это можно сопоставить с прямыми и обратными итераторами в vector.
Стоит отметить, что tr1::array поддерживает передачу нулевого размера массива, например:
Такая запись соответствует следующему: В зависимости от переданного размера: если он не 0 — берётся переданный размер, иначе — 1.2. std::array¶
Использование
array из std включает

Сравним array из tr1 и из std
template<typename _Tp, std::size_t _Nm>
struct array
{
typedef _Tp value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef value_type* iterator;
typedef const value_type* const_iterator;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
// Support for zero-sized arrays mandatory.
typedef _GLIBCXX_STD_C::__array_traits<_Tp, _Nm> _AT_Type; // # define _GLIBCXX_STD_C std
typename _AT_Type::_Type _M_elems;
}
В array можно отметить два момента:
// Support for zero-sized arrays mandatory.
typedef _GLIBCXX_STD_C::__array_traits<_Tp, _Nm> _AT_Type; // # define _GLIBCXX_STD_C std
typename _AT_Type::_Type _M_elems;
Поищем __array_traits в исходниках и увидим:
template<typename _Tp, std::size_t _Nm>
struct __array_traits
{
typedef _Tp _Type[_Nm];
static constexpr _Tp&
_S_ref(const _Type& __t, std::size_t __n) noexcept
{ return const_cast<_Tp&>(__t[__n]); }
};
Две строки кода выше можно понять так:
При написании кода, если нужно определить массив, мы можем записать:
Обработка переданного размера здесь сложнее, чем в tr1: используется частичная специализация шаблона для случая размера 0.template<typename _Tp, std::size_t _Nm>
struct __array_traits
{
typedef _Tp _Type[_Nm];
static constexpr _Tp&
_S_ref(const _Type& __t, std::size_t __n) noexcept
{ return const_cast<_Tp&>(__t[__n]); }
};
template<typename _Tp>
struct __array_traits<_Tp, 0>
{
struct _Type { };
static constexpr _Tp&
_S_ref(const _Type&, std::size_t) noexcept
{ return *static_cast<_Tp*>(nullptr); }
};
Похожие темы¶
- Глубокий анализ STL string | C++那些事
- Разбор вопросов собеседования про STL string | C++那些事
- Анализ исходников STL deque | C++那些事
- Оптимизация пустого базового класса EBO в STL | C++那些事
- Реализация хеш-таблицы своими руками | C++那些事
- Хеш-таблица STL hashtable | C++那些事
- Анализ исходников STL итераторов | C++那些事
- Анализ исходников STL list | C++那些事
- STL map и multimap | C++那些事
- Анализ исходников STL queue и stack | C++那些事