20.9. Адаптация встроенных массивов к библиотеке STL
Мы многократно указывали на недостатки встроенных массивов: они неявно преобразуют указатели при малейшем поводе, их нельзя скопировать с помощью присваивания, они не знают своего размера (см. раздел 20.5.2) и т.д. Кроме того, мы отмечали их преимущества: они превосходно моделируют физическую память.
Для того чтобы использовать преимущества массивов и контейнеров, мы можем создать контейнер типа array, обладающий достоинствами массивов, но не имеющий их недостатков. Вариант класса
array
был включен в стандарт как часть технического отчета Комитета по стандартизации языка С++. Поскольку свойства, включенные в этот отчет, не обязательны для реализации во всех компиляторах, класс
array
может не содержаться в вашей стандартной библиотеке. Однако его идея проста и полезна.
template <class T, int N> // не вполне стандартный массив
struct array {
typedef T value_type;
typedef T* iterator;
typedef T* const_iterator;
typedef unsigned int size_type; // тип индекса
T elems[N];
// не требуется явное создание/копирование/уничтожение
iterator begin() { return elems; }
const_iterator begin() const { return elems; }
iterator end() { return elems+N; }
const_iterator end() const { return elems+N; }
size_type size() const;
T& operator[](int n) { return elems[n]; }
const T& operator[](int n) const { return elems[n]; }
const T& at(int n) const; // доступ с проверкой диапазона
T& at(int n); // доступ с проверкой диапазона
T * data() { return elems; }
const T * data() const { return elems; }
};
Это определение не полно и не полностью соответствует стандарту, но оно хорошо иллюстрирует основную идею. Кроме того, оно позволяет использовать класс
array
, если его нет в вашей стандартной библиотеке. Если же он есть, то искать его следует в заголовке
<array>
. Обратите внимание на то, что поскольку объекту класса
array<T,N>
известен его размер
N
, мы можем (и должны) предусмотреть операторы
=
,
==
,
!=
как для класса
vector
.
Например, используем массив со стандартной функцией
high()
из раздела 20.4.2:
void f()
{
array<double,6> a = { 0.0, 1.1, 2.2, 3.3, 4.4, 5.5 };
array<double,6>::iterator p = high(a.begin(), a.end());
cout << " максимальное значение " << *p << endl;
}
Обратите внимание на то, что мы не думали о классе
array
, когда писали функцию
high()
. Возможность применять функцию
high()
к объекту класса
array
является простым следствием того, что в обоих случаях мы придерживались стандартных соглашений.
20.10. Обзор контейнеров
В библиотеке STL есть несколько контейнеров.
Огромный массив дополнительной информации об этих контейнерах и их использовании можно найти в книгах и документации, размещенной в Интернете. Перечислим несколько источников, заслуживающих доверия.
Austern, Matt, ed. “Technical Report on C++ Standard Library Extensions,” ISO/IEC PDTR 19768. (Colloquially known as TR1.)
Austern, Matthew H. Generic Programming and the STL. Addison-Wesley, 1999. ISBN 0201309564. Koenig, Andrew, ed. The C++ Standard. Wiley, 2003. ISBN 0470846747. (Not suitable for novices.)
Lippman, Stanley B., Josée Lajoie, and Barbara E. Moo. The C++ Primer. AddisonWesley, 2005. ISBN 0201721481. (Use only the 4th edition.)
Musser, David R., Gillmer J. Derge, and Atul Saini. STL Tutorial and Reference Guide: C++ Programming with the Standard Template Library, Second Edition. AddisonWesley, 2001. ISBN 0201379236.
Stroustrup, Bjarne. The C++ Programming Language. Addison-Wesley, 2000. ISBN 0201700735.
Документацию о реализации библиотеки STL и библиотеки потоков ввода-вывода компании SGI (Silicon Graphics International) можно найти на веб-странице www.sgi.com/tech/stl>. Обратите внимание, что на этой веб-странице приводятся законченные программы.
Документацию о реализации библиотеки STL компании Dinkumware можно найти на веб-странице www.dinkumware.com/manuals/default.aspx. (Имейте в виду, что существует несколько версий этой библиотеки.)
Документацию о реализации библиотеки STL компании Rogue Wave можно найти на веб-странице www2.roguewave.com/support/docs/index.cfm.
Вы чувствуете себя обманутым? Полагаете, что мы должны описать все контейнеры и показать, как их использовать? Это невозможно. Существует слишком много стандартных возможностей, полезных приемов и библиотек, чтобы описать их в одной книге. Программирование слишком богато возможностями, чтобы их мог освоить один человек. Кроме того, часто программирование — это искусство. Как программист вы должны привыкнуть искать информацию о возможностях языка, библиотеках и технологиях. Программирование — динамичная и быстро развивающаяся отрасль, поэтому необходимо довольствоваться тем, что вы знаете, и спокойно относиться к тому, что существуют вещи, которых вы не знаете. “Искать в справочнике” — это вполне разумный ответ на многие вопросы. По мере увеличения вашего опыта, вы будете все чаще поступать именно так.
С другой стороны, вы обнаружите, что, освоив классы
vector
,
list
и
map
, а также стандартные алгоритмы, описанные в главе 21, вы легко научитесь работать с остальными контейнерами из библиотеки STL. Вы обнаружите также, что знаете все, что требуется для работы с нестандартными контейнерами, и сможете их программировать сами.