Урок №94. Введение в std::array

  Юрий  | 

  Обновл. 16 Авг 2020  | 

 36978

 ǀ   13 

На предыдущих уроках мы подробно говорили о фиксированных и динамических массивах. Хотя они очень полезны и активно используются в языке C++, у них также есть свои недостатки: фиксированные массивы распадаются в указатели, теряя информацию о своей длине; в динамических массивах проблемы могут возникнуть с освобождением памяти и с попытками изменить их длину после выделения.

Поэтому в Стандартную библиотеку C++ добавили функционал, который упрощает процесс управления массивами: std::array и std::vector. На этом уроке мы рассмотрим std::array, а на следующем — std::vector.

Введение в std::array

Представленный в C++11, std::array — это фиксированный массив, который не распадается в указатель при передаче в функцию. std::array определяется в заголовочном файле array, внутри пространства имен std. Объявление переменной std::array следующее:

Подобно обычным фиксированным массивам, длина std::array должна быть установлена во время компиляции. std::array можно инициализировать с использованием списка инициализаторов или uniform-инициализации:

В отличие от стандартных фиксированных массивов, в std::array вы не можете пропустить (не указывать) длину массива:

Также можно присваивать значения массиву с помощью списка инициализаторов:

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

Так же, как и в стандартных фиксированных массивах, оператор индекса не выполняет никаких проверок на диапазон. Если указан недопустимый индекс, то произойдут плохие вещи.

std::array поддерживает вторую форму доступа к элементам массива — функция at(), которая осуществляет проверку диапазона:

В примере, приведенном выше, вызов myarray.at(1) проверяет, есть ли элемент массива под номером 1, и, поскольку он есть, возвращается ссылка на этот элемент. Затем мы присваиваем ему значение 7. Однако, вызов myarray.at(8) не срабатывает, так как элемента под номером 8 в массиве нет. Вместо возвращения ссылки, функция at() выдает ошибку, которая завершает работу программы (на самом деле выбрасывается исключение типа std::out_of_range. Об исключениях мы поговорим на соответствующих уроках). Поскольку проверка диапазона выполняется, то функция at() работает медленнее (но безопаснее), чем оператор [].

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

Размер и сортировка


С помощью функции size() можно узнать длину массива:

Результат:

length: 4

Поскольку std::array не распадается в указатель при передаче в функцию, то функция size() будет работать, даже если её вызвать из другой функции:

Результат тот же:

length: 4

Обратите внимание, Cтандартная библиотека C++ использует термин «размер» для обозначения длины массива — не путайте это с результатами выполнения оператора sizeof с обычным фиксированным массивом, когда возвращается фактический размер массива в памяти (размер элемент * длина массива).

Также обратите внимание на то, что мы передаем std::array по ссылке (константной). Это делается по соображениям производительности для того, чтобы компилятор не выполнял копирование массива при передаче в функцию.

Правило: Всегда передавайте std::array в функции по обычной или по константной ссылке.

Поскольку длина массива всегда известна, то циклы foreach также можно использовать с std::array:

Вы можете отсортировать std::array, используя функцию std::sort(), которая находится в заголовочном файле algorithm:

Результат:

1 2 4 7 8

Функция сортировки использует итераторы, которые мы еще не рассматривали. О них мы поговорим несколько позже.

Заключение

std::array — это отличная замена стандартных фиксированных массивов. Массивы, созданные с помощью std::array, более эффективны, так как используют меньше памяти. Единственными недостатками std::array по сравнению со стандартными фиксированными массивами являются немного неудобный синтаксис и то, что нужно явно указывать длину массива (компилятор не будет вычислять её за нас). Но это сравнительно незначительные нюансы. Рекомендуется использовать std::array вместо стандартных фиксированных массивов в любых нетривиальных задачах.


Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (199 оценок, среднее: 4,91 из 5)
Загрузка...

Комментариев: 13

  1. Аватар Георгий:

    Кстати, начиная с C++17 компилятор может вывести не только длину, но и тип массива:

  2. Аватар Снова я:

    Можете объяснить этот момент?

    Почему елементам 2 и 3, а не 1 и 2 ?

    1. Аватар Мгер:

      тут все что не заполнено, получает значение по умолчанию.
      так же как и с обычным массивом:

  3. Аватар Антон:

    "std::array — это отличная замена стандартных фиксированных массивов. Они более эффективны, так как используют меньше памяти." Это вдруг почему?

    1. Аватар Георгий:

      Не по чему. На деле, std::array и обычный массив подуцируют один и тот же ассемблерный код (проверял в VS). С std::array удобнее присваивание целого массива, передача в функции, копирование и т. д. (с обычными массивами тут большие проблемы). По эффективности они абсолютно идентичны

  4. Аватар Арман:

    Ну конечно array будет знать свой размер , если указывать его в параметрах :

    А если функция должна работать с разными array. Передавать размер как аргумент или я что то не понял?

    1. Аватар Мгер:

      Не совсем то что ты хочешь, но вот еще как можно сделать:

  5. Аватар Андрей:

    А как на счет двумерного массива?

    1. Юрий Юрий:

      Двумерный массив объявляется как:

      Здесь myarray — это название вашего двумерного массива, а сам двумерный массив создается с помощью вложенного массива (т.е. один внутри другого).

      1. Аватар Vlad:

        Это очень неудобно. Тут лучше использовать обычные квадратные скобки

        1. Аватар Мгер:

          с обычным массивом много что нельзя сделать. Например это:

      2. Аватар alex_1988:

        Покажите синтаксис использования функции at() для двухмерного массива и почему size() не показывает суммарную длину всех ячеек двухмерного массива?

        1. Аватар Сергей:

          Спасибо alex_1988 за вопросы.
          И конечно автору сайта за качественный перевод.

          Синтаксис использования функции at() в двумерных массивах выглядит так: myarray2.at().at()

          Но есть особенность, например:

          Здесь сначала идет проверка последнего (второго) индекса массива myarray2 (объявлено 5, проверяем от 0 до 4), а затем предпоследнего (первого) индекса массива myarray2 (объявлено 10, проверяем от 0 до 9).

Добавить комментарий

Ваш E-mail не будет опубликован. Обязательные поля помечены *