// деструктор и присваивание
T& operator[] (int n); // доступ: возвращает ссылку
const T& operator[] (int n) const;
T* data() { return elem; } // преобразование в тип T*
const T* data() const { return elem; }
int size() const { return N; }
}
Мы можем использовать класс array
(см. также раздел 20.7) примерно так:
array
array
const int max = 1024;
void some_fct(int n)
{
array
array
// неизвестно
// ...
array
// ...
loc = loc2; // восстанавливаем
// ...
}
Ясно, что класс array очень простой — более простой и менее мощный, чем класс vector
, — так почему иногда следует использовать его, а не класс vector
? Один из ответов: “эффективность”. Размер объекта класса array известен на этапе компиляции, поэтому компилятор может выделить статическую память (для глобальных объектов, таких как gb
) или память в стеке (для локальных объектов, таких как loc
), а не свободную память. Проверяя выход за пределы диапазона, мы сравниваем константы (например, размер array
имеет много преимуществ над классом vector без нарушения основного ограничения (запрета на использование свободной памяти).
Поставим противоположный вопрос: “Почему бы просто не использовать класс vector
?”, а не “Почему бы просто не использовать встроенные массивы?” Как было показано в разделе 18.5, массивы могут порождать ошибки: они не знают своего размера, они конвертируют указатели при малейшей возможности и неправильно копируются; в классе array
, как и в классе vector
, таких проблем нет. Рассмотрим пример.
double* p = ad; // ошибка: нет неявного преобразования
// в указатель
double* q = ad.data(); // OK: явное преобразование
template
{
for (int i = 0; i
Эту функцию printout()
можно вызвать как в классе array
, так и в классе vector
.
printout(ad); // вызов из класса array
vector
// ...
printout(vi); // вызов из класса vector
Это простой пример обобщенного программирования, демонстрирующий доступ к данным. Он работает благодаря тому, что как для класса array
, так и для класса vector
используется один и тот же интерфейс (функции size()
и операция индексирования). Более подробно этот стиль будет рассмотрен в главах 20 и 21.
19.3.5. Вывод шаблонных аргументов
Создавая объект конкретного класса на основе шаблонного класса, мы указываем шаблонные аргументы. Рассмотрим пример.
array
array
template
{
for (int i = 0; i
}
void f()
{
fill(buf, 'x'); // для функции fill() параметр T — char,
// а N == 1024,
// потому что аргументом является объект buf
fill(b2,0.0); // для функции fill() параметр T — double,
// а N == 10,
// потому что аргументом является объект b2
}