cpp

Класс array: массив фиксированного размера

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

#include <array>

Создание массива и заполнение значениями

Объявление класса array:

template<typename T, std::size_t N> struct array;

При создании экземпляра класса array после названия класса внутри угловых скобок через запятую задается тип данных элементов массива и его фиксированный размер:

std::array<int, 10> arr;
std::cout << arr.size() << std::endl;     // 10
std::cout << arr.max_size() << std::endl; // 10
std::cout << std::boolalpha <<
             arr.empty() << std::endl;    // false

В этом примере мы создали массив элементов типа int, содержащий 10 элементов. Массив имеет фиксированный размер и размещается в обычной памяти, а не в динамической. Изменить размер массива после создания объекта нельзя. Получить количество элементов позволяют методы size() и max_size(). Для определения, является ли массив пустым, можно использовать метод empty().

После создания объекта все элементы массива будут иметь произвольные значения, так называемый «мусор». Чтобы присвоить значения элементам массива при инициализации, нужно указать их через запятую внутри фигурных скобок:

std::array<int, 5> arr1{1, 2, 3, 4, 5};
for (int &el : arr1) std::cout << el << ' ';
std::cout << std::endl; // 1 2 3 4 5
std::array<int, 5> arr2 = {6, 7, 8};
for (int &el : arr2) std::cout << el << ' ';
std::cout << std::endl; // 6 7 8 0 0

Если количество значений внутри фигурных скобок меньше количества элементов массива, то остальные элементы автоматически получат значение 0. Присвоить всем элементам массива одинаковое значение позволяет метод fill():

std::array<int, 5> arr;
arr.fill(1);
for (int &el : arr) std::cout << el << ' ';
std::cout << std::endl; // 1 1 1 1 1

С помощью метода swap() можно поменять элементы двух массивов местами:

std::array<int, 5> arr1, arr2;
arr1.fill(1);
arr2.fill(2);
arr1.swap(arr2);
for (int &el : arr1) std::cout << el << ' ';
std::cout << std::endl; // 2 2 2 2 2
for (int &el : arr2) std::cout << el << ' ';
std::cout << std::endl; // 1 1 1 1 1

Над двумя объектами класса array определены операции ==, !=, <, <=, > и >=. Пример сравнения двух объектов:

std::array<int, 2> arr1 = {5, 1};
std::array<int, 2> arr2 = {5, 1};
if (arr1 == arr2) {
   std::cout << "arr1 == arr2" << std::endl;
}

Кроме того, один объект можно присвоить другому объекту. В этом случае выполняется поэлементное копирование. Пример:

std::array<int, 2> arr1 = {5, 1}, arr2;
arr2 = arr1;
for (int &el : arr2) std::cout << el << ' ';
std::cout << std::endl; // 5 1

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

К любому элементу контейнера можно обратиться как к элементу массива. Достаточно указать его индекс в квадратных скобках. Нумерация начинается с нуля. Можно как получить значение, так и изменить его. Если индекс выходит за границы диапазона, то возвращаемое значение не определено. Пример доступа к элементу по индексу:

std::array<int, 2> arr = {1, 1};
std::cout << arr[0] << " " << arr[1] << std::endl; // 1 1
arr[1] = 2;
std::cout << arr[0] << " " << arr[1] << std::endl; // 1 2

Для доступа к элементам предназначены следующие методы:

  • at() — возвращает ссылку на элемент, расположенный по индексу pos. Метод позволяет как получить значение, так и изменить его. Если индекс выходит за границы диапазона, то метод генерирует исключение. Прототипы метода:
reference at(size_type pos);
const_reference at(size_type pos) const;

Пример:

std::array<int, 2> arr = {1, 1};
arr.at(1) = 2;
std::cout << arr.at(0) << " " << arr.at(1) << std::endl; // 1 2
  • front() — возвращает ссылку на первый элемент. Метод позволяет как получить значение, так и изменить его. Прототипы метода:
reference front() noexcept;
const_reference front() const noexcept;
  • back() — возвращает ссылку на последний элемент. Метод позволяет как получить значение, так и изменить его. Прототипы метода:
reference back() noexcept;
const_reference back() const noexcept;

Пример:

std::array<int, 3> arr = {1, 2, 3};
std::cout << arr.front() << " " << arr.back() << std::endl;
// 1 3
arr.front() = 0;
arr.back() = 5;
std::cout << arr[0] << " " << arr[2] << std::endl; // 0 5
  • begin(), end(), cbegin(), cend(), rbegin(), rend(), crbegin() и crend() — возвращают итераторы (см. разд. 16.1.1). Изменим и выведем значение первого элемента:
std::array<int, 3> arr = {1, 2, 3};
std::array<int, 3>::iterator it = arr.begin();
std::cout << *it << std::endl; // 1
*it = 0;
std::cout << *it << std::endl; // 0

Вместо методов begin() и end() можно воспользоваться одноименными функциями. Выведем значение последнего элемента:

std::array<int, 3> arr = {1, 2, 3};
std::array<int, 3>::iterator it = std::end(arr);
std::cout << *(--it) << std::endl; // 3

Все элементы размещаются в памяти последовательно. Поэтому имеется возможность перебора элементов с помощью указателей. Для указателей определены специальные типы:

  • pointer — обычный указатель. Можно как получить значение, так и изменить:
typedef T value_type;
typedef value_type* pointer;
  • const_pointer — константный указатель. Изменить значение нельзя:
typedef const value_type* const_pointer;

Присвоить указателю адрес первого элемента позволяет метод data(). Прототипы метода:

pointer data() noexcept;
const_pointer data() const noexcept;

Пример:

std::array<int, 3> arr = {1, 2, 3};
int *p = arr.data();
std::cout << *p << std::endl;     // 1
*p = 0;
std::cout << arr[0] << std::endl; // 0

Перебор элементов

Перебрать все элементы можно с помощью цикла for each, итераторов и алгоритма for_each(). Пример использования цикла for each:

std::array<int, 3> arr;
// Заполняем массив значениями
int n = 1;
for (int &el : arr) {
   el = n++;
}
// Выводим значения
for (int &el : arr) std::cout << el << ' ';
std::cout << std::endl; // 1 2 3

Пример перебора элементов с помощью итераторов и цикла for в прямом и обратном порядке:

std::array<int, 3> arr = {1, 2, 3};
std::array<int, 3>::iterator it1, it2;
// Перебор в прямом порядке
for (it1 = arr.begin(), it2 = arr.end(); it1 != it2; ++it1) {
   std::cout << *it1 << ' ';
}
std::cout << std::endl; // 1 2 3
// Перебор в обратном порядке
std::array<int, 3>::reverse_iterator it3, it4;
for (it3 = arr.rbegin(), it4 = arr.rend(); it3 != it4; ++it3) {
   std::cout << *it3 << ' ';
}
std::cout << std::endl; // 3 2 1

Пример перебора элементов с помощью итераторов и цикла while:

std::array<int, 3> arr = {1, 2, 3};
auto it1 = arr.begin(), it2 = arr.end();
while (it1 != it2) {
   std::cout << *it1++ << ' ';
}
std::cout << std::endl; // 1 2 3

С помощью алгоритма for_each() умножим значение каждого элемента массива на 2, а затем выведем все значения в окно консоли:

// #include <algorithm>
std::array<int, 3> arr = {1, 2, 3};
// Умножаем все элементы на 2
std::for_each( arr.begin(), arr.end(),
               [](int &a) { a *= 2; } );
// Выводим значения всех элементов
std::for_each( arr.begin(), arr.end(),
               [](int &a){ std::cout << a << ' '; } );
std::cout << std::endl; // 2 4 6

Учебник C++ (Qt Creator и MinGW)
Учебник C++ (Qt Creator и MinGW) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов

cpp