Встроенный (примитивный) массив C ++ имеет несколько недостатков, которые затрудняют его использование во многих программах. Одна из основных проблем с примитивным массивом заключается в том, что нет функции, возвращающей размер массива. Это означает, что когда вам нужен размер массива для чего-то вроде управления циклом for, вы должны использовать переменную или константу, которая хранит размер массива. Другая проблема с примитивным массивом заключается в том, что вы не можете использовать его для передачи функции, вам также необходимо передать его размер. Вы не можете использовать диапазон для цикла с примитивным массивом в функции, потому что функция не может получить доступ к информации, необходимой для настройки итератора.

Решением использования примитивного массива является использование класса array, который является частью стандартной библиотеки шаблонов (STL) и его набора контейнеров. В этой статье я расскажу, как использовать этот класс в ваших программах на C ++.

Особенности класса массива

array класс - это шаблонный класс, найденный в STL. Он считается одним из классов контейнеров STL, поэтому имеет многие из тех же функций, что и другие контейнеры STL, такие как класс vector. Класс array следует выбирать среди других контейнеров STL, если вам нужна фиксированная числовая последовательность, потому что, как и примитивный массив, класс array обеспечивает произвольный доступ, а память, используемая для хранения его элементов, выделяется в стеке, потому что память никогда не требуется для быть перераспределенным по мере необходимости, например, с классом vector.

Создание объектов класса массива

Есть несколько способов создать новый объект array. Один из способов - просто объявить объект с типом данных и размером (количеством элементов), например:

array<int, 10> numbers;

Массив numbers предназначен для хранения 10 целых чисел. Объект также автоматически инициализируется значением по умолчанию для типа данных int, поэтому в массиве хранится 10 нулей.

Вы также можете инициализировать новый объект array данными, используя список инициализаторов:

array<int, 5> numbers {1,2,3,4,5};

Если вы объявляете размер и список инициализаторов, но не предоставляете данные для размера, для остальных элементов устанавливается значение по умолчанию для типа данных:

array<int, 10> numbers {1,2,3,4,5};

Новый объект array может быть создан через присвоение (конструктор копирования) из другого array объекта:

array<int, 10> numbers {1,2,3,4,5};
array<int, 10> nums = numbers;

Размер Функция

Прежде чем я перейду к операциям array class, мне нужно охватить одну важную функцию, которая необходима для многих операций с массивами - функцию size. Как я упоминал в начале этой статьи, одна из проблем с примитивными массивами заключается в том, что у них нет функции size или другой функции, возвращающей размер массива. У класса array есть функция size, и ее следует использовать каждый раз, когда вы обращаетесь к объекту класса array. В следующих разделах я продемонстрирую, как использовать эту функцию.

Доступ к элементам массива

Самый очевидный способ получить доступ к элементам массива - использовать нотацию индекса, как в этом примере:

#include <iostream>
#include <array>
using namespace std;
int main()
{
  array<int, 5> numbers {1,2,3,4,5};
  for (unsigned i = 0; i < numbers.size(); i++) {
    cout << numbers[i] << " ";
  }
  return 0;
}

Вы также можете использовать функцию at вместо оператора []:

for (unsigned i = 0; i < numbers.size(); i++) {
  cout << numbers.at(i) << " ";
}

Конечно, вы также можете использовать цикл range for и полностью избегать функции size:

for (int n : numbers) {
  cout << n << " ";
}

Для объектов массива доступны две специальные функции доступа: front и back. Эти функции возвращают первый элемент массива и последний элемент соответственно:

array<int, 5> numbers {1,2,3,4,5};
cout << "The first element is: " << numbers.front() << endl;
cout << "The last element is: " << numbers.back() << endl;

Объекты массива используют итераторы

Вы можете использовать итераторы для обхода объектов массива. Доступны стандартные функции итератора: begin, end, rbegin и rend . Вот пример работы этих функций в программе, которая отображает массив от начала до конца, а затем в обратном порядке:

int main()
{
  array<string, 4> beatles =
    {"John", "Paul", "George", "Ringo"};
  cout << "The Beatles in order of joining the group: "
       << endl << endl;
  for (auto iter = beatles.begin(); iter != beatles.end();
       iter++) {
    cout << *iter << endl;
  }
  cout << endl << "The Beatles in reverse order of joining: "
       << endl << endl;
  for (auto riter = beatles.rbegin(); riter != beatles.rend();
       riter++) {
    cout << *riter << endl;
  }
  return 0;
}

Результат этой программы:

The Beatles in order of joining the group:
John
Paul
George
Ringo
The Beatles in reverse order of joining:
Ringo
George
Paul
John

Другое использование итераторов - в алгоритмах STL. Вот программа, которая сортирует array чисел:

#include <iostream>
#include <array>
#include <algorithm>
using namespace std;
int main()
{
  array<int, 10> numbers {6,1,10,5,9,2,8,3,7,4};
  for (int n : numbers) {
    cout << n << " ";
  }
  cout << endl << endl;
  sort(numbers.begin(), numbers.end());
  for (int n : numbers) {
    cout << n << " "; // 1 2 3 4 5 6 7 8 9 10
  }
  return 0;
}

Преимущества массива над примитивным массивом C ++

Ранее в статье я упоминал два преимущества использования класса array по сравнению с примитивным массивом. Обе причины вращаются вокруг концепции, согласно которой класс array имеет функцию size, доступную для использования в циклах, где вы хотите остановиться в конце массива. Примитивные массивы, которые передаются в функции, должны передаваться с указанием их размера, потому что вы не можете использовать цикл range for для примитивного массива в функции, потому что функция не может получить доступ к нужной информации для использования цикла range for.

Вот пример, который не работает:

void computeAverage(int arr[]) {
  for (int n : arr) {
    cout << n << " ";
  }
}
int main()
{
  const int SIZE = 5;
  int grades[SIZE] = {88, 71, 91, 85, 93};
  printArray(grades);
  return 0;
}

Ошибка гласит: «begin не было объявлено в этой области». Компилятор не может использовать функцию begin для создания итератора, поскольку массив был создан в функции main за пределами области действия функции computeAverage.

Однако вы можете успешно использовать объект array в этой программе:

#include <iostream>
#include <array>
using namespace std;
void printArray(auto arr) {
  for (int n : arr) {
    cout << n << " ";
  }
}
int main()
{
  array<int, 5> grades = {88, 71, 91, 85, 93};
  printArray(grades); // displays 88 71 91 85 93
  return 0;
}

Обратите внимание, что я использовал ключевое слово auto для ввода параметра функции, чтобы компилятор мог определить, как обрабатывать параметр во время выполнения.

Заключительная рекомендация

Класс STL array обеспечивает ту же функциональность, что и примитивный массив, а также многие удобства, которые делают его более полезным, когда вам нужен последовательный контейнер, к которому можно получить произвольный доступ. Конечно, это не отменяет более общую рекомендацию использовать vector для любого типа массива для большинства приложений, поскольку векторы имеют гораздо большую гибкость, чем массивы (любого типа), если вы не храните большой набор данных и не нуждаетесь в произвольном доступе. массивы эффективности обеспечивают.

Спасибо, что прочитали эту статью, и пишите мне с комментариями и предложениями.