Контейнер array из одноименного модуля <array> представляет аналог массива. Он также имеет фиксированный размер.
Для создания объекта array в угловых скобках после названия типа необходимо передать его тип и размер:
#include <array>
int main()
{
std::array<int, 5> numbers; // состоит из 5 чисел int
}
В данном случае определен объект array из 5 чисел типа int. По умолчанию все элементы контейнера имеют неопределенные значения.
Чтобы инициализировать контейнер определенными значениями, можно использовать инициализатор - в фигурных скобках передать значения элементам контейнера:
std::array<int, 5> numbers {}; // состоит из 5 нулей
В данном случае пустой инициализатор инициализирует все элементы контейнера numbers нулями. Также можно указать конкретные значения для элементов:
std::array<int, 5> numbers {2, 3, 4, 5, 6};
Фиксированный размер накладывает ограничение на инициализацию: количество передаваемых контейнеру элементов не должно превышать его размер. Можно передать меньше значений, которые будут переданы первым элементам контейнера, а остальные элементы получат значения по умолчанию (например, для целочисленных типов это число 0):
std::array<int, 5> numbers {2, 3, 4}; // {2, 3, 4, 0, 0}
Однако если при инициализации мы предадим большее количество элементов, нежели размер контейнера, то мы столкнемся с ошибкой.
Стоит отметить, что начиная со стандарта C++17 при инициализации можно не указывать тип и количество элементов - компилятор выводит это автоматически исходя из списка инициализации:
std::array numbers {2, 3, 4, 5, 6};
Однако в этом случае в списке инициализации в фигурных скобках должно быть как минимум одно значение.
Для доступа к элементам контейнера array можно применять тот же синтаксис, что при работе с массивами - в квадратных скобках указывать индекс элемента, к которому идет обращение:
#include <array>
#include <iostream>
int main()
{
std::array<int, 5> numbers {2, 3, 4, 5, 6};
// получаем значение элемента
int n = numbers[2];
std::cout << "n = " << n << std::endl; // n = 4
// меняем значение элемента
numbers[2] = 12;
std::cout << "numbers[2] = " << numbers[2] << std::endl; // numbers[2] = 12
}
С помощью стандартных циклов можно перебрать контейнер array:
#include <iostream>
#include <array>
#include <string>
int main()
{
const unsigned n = 5;
std::array<std::string, n> people { "Tom", "Alice", "Kate", "Bob", "Sam" };
// обращение через индексы
for(int i{}; i < n; i++)
{
std::cout << people[i] << std::endl;
}
std::cout << std::endl;
// перебор последовательности
for (auto person : people)
{
std::cout << person << std::endl;
}
}
В контейнер array нельзя добавлять новые элементы, так же как и удалять уже имеющиеся. Основные функции типа array, которые мы можем использовать:
size(): возвращает размер контейнера
at(index): возвращает элемент по индексу index
front(): возвращает первый элемент
back(): возвращает последний элемент
fill(n): присваивает всем элементам контейнера значение n
Применение методов:
#include <iostream>
#include <array>
#include <string>
int main()
{
std::array<std::string, 3> people { "Tom", "Bob", "Sam" };
std::string second = people.at(1); // Bob
std::string first = people.front(); // Tom
std::string last = people.back(); // Sam
std::cout << second << std::endl; // Bob
std::cout << first << std::endl; // Tom
std::cout << last << std::endl; // Sam
// присваиваем всем элементам "Undefined"
people.fill("Undefined"); // people = { "Undefined", "Undefined", "Undefined" }
// проверяем
for (int i{}; i< people.size(); i++)
{
std::cout << people[i] << std::endl;
}
}
Несмотря на то, что объекты array похожи на обычные массивы, тип array более гибок. Например, мы не можем присваивать одному массиву напрямую значения второго массива. В то же время объекту array мы можем передавать данные другого объекта array:
std::array<int, 5> numbers1 { 1, 2, 3, 4, 5 };
std::array<int, 5> numbers2 = numbers1; // так можно сделать
int nums1[] = { 1,2,3,4,5 };
//int nums2[] = nums1; // так нельзя следать
Также мы можем сравнивать два контейнера array:
std::array<int, 5> numbers1 { 1, 2, 3, 4, 5 };
std::array<int, 5> numbers2 { 1, 2, 3, 4, 5 };
std::cout << std::boolalpha << (numbers1 == numbers2) << std::endl; // true
std::cout << std::boolalpha << (numbers1 != numbers2) << std::endl; // false
std::cout << std::boolalpha << (numbers1 > numbers2) << std::endl; // false
std::cout << std::boolalpha << (numbers1 < numbers2) << std::endl; // false
Два контейнера сравниваются поэлементно. Так, в примере выше очевидно, что контейнеры numbers1 и numbers2 равны. Тогда как сравнение массивов начиная со стандарта C++20 объявлено устаревшим.