No Image

Создание одномерного массива c

СОДЕРЖАНИЕ
248 просмотров
10 марта 2020

Вы можете объявить одномерный массив, содержащий пять целых чисел, как показано в следующем примере: You can declare a single-dimensional array of five integers as shown in the following example:

Этот массив содержит элементы с array[0] по array[4] . This array contains the elements from array[0] to array[4] . С помощью оператора new можно создать массив и инициализировать его элементы, используя значения по умолчанию. The new operator is used to create the array and initialize the array elements to their default values. В этом примере при инициализации всем элементам массива присваиваются нулевые значения. In this example, all the array elements are initialized to zero.

Таким же образом можно объявить массив, в котором хранятся строковые элементы. An array that stores string elements can be declared in the same way. Например: For example:

Инициализация массива Array Initialization

Массив можно инициализировать при объявлении. В этом случае не требуется спецификатор длины, поскольку он уже задан по числу элементов в списке инициализации. It is possible to initialize an array upon declaration, in which case, the length specifier is not needed because it is already supplied by the number of elements in the initialization list. Например: For example:

Массив строк можно инициализировать таким же образом. A string array can be initialized in the same way. Ниже приведено объявление массива строк, где каждый элемент массива инициализируется с использованием названия дня: The following is a declaration of a string array where each array element is initialized by a name of a day:

Если массив инициализируется при объявлении, вы можете использовать следующие сочетания клавиш: When you initialize an array upon declaration, you can use the following shortcuts:

Переменную массива можно объявить без инициализации, однако при присвоении массива этой переменной необходимо использовать оператор new . It is possible to declare an array variable without initialization, but you must use the new operator when you assign an array to this variable. Например: For example:

В C# 3.0 представлены неявно типизированные массивы. C# 3.0 introduces implicitly typed arrays. Дополнительные сведения см. в разделе Неявно типизированные массивы. For more information, see Implicitly Typed Arrays.

Массивы типов значений и ссылочных типов Value Type and Reference Type Arrays

Рассмотрим следующее объявление массива: Consider the following array declaration:

Результат этого оператора зависит от того, является ли SomeType типом значения или ссылочным типом. The result of this statement depends on whether SomeType is a value type or a reference type. Если это тип значения, оператор создает массив из 10 элементов, каждый из которых имеет тип SomeType . If it is a value type, the statement creates an array of 10 elements, each of which has the type SomeType . Если SomeType является ссылочным типом, этот оператор создает массив из 10 элементов, каждый из которых инициализируется с использованием ссылки NULL. If SomeType is a reference type, the statement creates an array of 10 elements, each of which is initialized to a null reference.

Читайте также:  Что такое выпуклый четырехугольник рисунок

Дополнительные сведения о типах значений и ссылочных типах см. в разделе Типы. For more information about value types and reference types, see Types.

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

Содержание

Объявление массива в C/C++

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

В C++ массивы статичны: вы не сможете изменить размер или тип элементов после объявления.

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

Вы можете получать доступ к элементам массива, используя индексы и оператор [] . Допустим, вы объявили массив marks , как показано ниже. К первому элементу можно обратиться выражением marks[0] , ко второму – выражением marks[1] , и так далее. Доступ всегда начинается с единицы, а индекс последнего элемента на единицу меньше размера массива.

Инициализация массива при объявлении

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

Обход элементов массива в цикле

Узнать число элементов в массиве можно функцией std::size. Обойти можно, используя цикл по индексам либо range-based for:

Неопределённое поведение: выход за границы (out of bounds)

Выход за пределы массива является неопределённым поведением (англ. undefined behavior). Нет гарантий, как поведёт себя программа в этом случае. Высока вероятность, что вы испортите память других переменных, но эффект может различаться в разных режимах компиляции:

Передача массива как параметра функции

Массив в стиле языка C хранит только указатель на начало и не хранит свой размер, что и создаёт сложность в передаче в функцию. Размер массива известен во время компиляции, но не известен во время выполнения. Поэтому передать размер можно несколькими не очень очевидными путями:

Читайте также:  Iphone 6s нет сети imei есть

Динамически изменяемый массив

Обычные массивы имеют неизменный размер. Вы можете ввести вспомогательную переменную, которая бы хранила число реально используемых ячеек массива. Но и в этом случае вы не сможете использовать элементов больше, чем задано при компиляции в виде размера массива.

Так мог бы выглядеть имитация динамического массива:

Класс std::vector

Стандартная библиотека C++ содержит шаблонный класс vector, который работает как динамический массив произвольного размера. Размер может расти до тех пор, пока у операционной системы есть область памяти подходящего размера (вплоть до нескольких гигабайт).

Класс является шаблонным, то есть при объявлении переменной потребуется параметризовать шаблон класса vector типом элемента:

Использование вектора похоже на использование массива:

  • работает запрос элемента ages[index] , причём индексация так же начинается с нуля
  • при выходе за границы динамического массива так же возникает неопределённое поведение (англ. undefined behavior)
  • работает перебор элементов с помощью индексов, range-based for или итераторов
  • есть метод size для получения размера: ages.size()

Добавление элементов в конец массива

Для добавления существует два метода: push_back и emplace_back

  • push_back получает значение элемента и добавляет в конец
  • emplace_back работает сложнее: он получает параметры, необходимые конструктору элемента, и конструирует его прямо в конце массива

Вы можете практически всегда использовать push_back. Метод pop_back можно использовать для удаления элемента:

В документации std::vector можно прочитать о других методах.

Перемещение элементов в памяти при изменении массива

Динамический массив использует для хранения элементов динамическую память (так же известную как “куча”, англ. heap). При добавлении большого числа элементов динамический массив несколько раз перераспределяет память, поскольку выделенной ранее линейной области памяти уже не хватает для хранения всех элементов. Обычно при нехватке памяти под очередной элемент vector запрашивает новую область памяти в 1,5-2 раза больше предыдущей, перемещает в неё уже существующие элементы и добавляет в конец новый, а затем освобождает старую область памяти.

Если не сообразили, как это происходит, взгляните на картинку:

Новая область находится уже другом месте, потому что менеджер динамической памяти не мог просто взять и расширить старую область (ведь сразу за ней находилась чужая память). Поэтому все итераторы, ссылки и указатели на элементы могут стать некорректными после любого изменения массива!

Метод erase для удаления элементов из середины

Метод erase класса vector получает итератор и уничтожает элемент, на который итератор указывает:

Читайте также:  U0442 u0435 u0441 u0442

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

Использование итератора, ссылки или указателя на элемент после перераспределения памяти в массиве является неопределённым поведением: скорее всего произойдёт падение программы либо будет пропущено несколько элементов коллекции. Это показано в примере ниже:

Если вы запустите этот код, вы можете увидеть что угодно. Скорее всего программа выведет 10 38 99 , хотя должна вывести 10 23 7 38 99 по замыслу автора.

Для решения этой проблемы метод erase возвращает новый, валидный итератор на элемент, следующий после удалённого. Если элемент был последним, erase вернёт итератор end. Учитывая это, мы можем исправить код, чтобы новое значение it либо получалось из erase, либо получалось путём инкремента:

Программа корректно напечатает 10 23 7 38 99 .

  • Для любого массива C++, хранящего N элементов, индекс последнего элемента всегда N-1, а индекс первого элемента 0
  • Для создания обычного массива компилятору нужно указать тип хранимых элементов и предполагаемое количество ячеек для хранения тех элементов.
  • Массивам обязательно нужно указывать тип, как и обычным переменным. Типы массивов задаются те же, что для переменных.
  • Количество хранимых элементов указывается в квадратных скобках во время объявления массива.
  • Квадратные скобки могут служит некоторого рода индикатором, сообщающем о том, что работа происходит с массивом.
  • Каждый отдельный элемент обычного массива вытаскивается по индексу, т. е. по номеру ячейки.
  • Номер вытаскиваемого элемента надо начинать расчитывать с ноля, а не единицы.
  • Номера элементов массива называют индексами массива.
  • Массив возможно инициализировать значениями. Без инициализации массива значениями внутр массива оказывается информационный мусор.
  • Внешние и статические массивы можно инициализировать
  • Автоматические и регистровые массивы инициализировать нельзя
  • Количество элементов обычного массива задаётся только константным значением.
  • Задача: Получить сумму всех элементов массива.
  • Начинающим программистам и пришлым программистам (например, с Turbo Pascal) сложно контроллировать границы массивов. Одна из очень распространённых ошибок всех новичков — выход за пределы массива. Отсчёт в С++ ведётся с нуля!
  • Имя массива это только идентификатор. По стандарту массивы имеют право приводиться к типу "указатель", при этом получаемый указатель указывает на первый элемент массива.

Такие дела. Типы данных "указатель" и "массив" отличны друг от друга. Хотя часто имя массива используется как указатель на первый хранимый элемент, в некоторых случаях поведения у имени массива и переменной, тип которой указатель, будут отличаться.

Комментировать
248 просмотров
Комментариев нет, будьте первым кто его оставит

Это интересно
Adblock
detector