Массивы

Массив – это серия элементов одного типа, с одним именем (идентификатором), которые размещаются в смежных ячейках памяти, на которые можно ссылаться, добавляя индекс к уникальному идентификатору.Это означает, что, например, 5 значений типа int могут быть объявлены как массив 5 разных переменных с именем foo: foo[5] (каждый со своим собственным идентификатором c индексом foo[i]).Например, массив, содержащий 5 целых значений int foo может быть представлен как:
Эти элементы нумеруются от 0 до 4, являясь 0 первым и 4 последним;Как и регулярная переменная, массив должен быть объявлен до его использования. Следовательно, массив с пятью элементами типа может быть объявлен как:int foo [5];ПРИМЕЧАНИЕ. Поле в квадратных скобках [], представляющее количество элементов в массиве, должно быть постоянным выражением , так как массивы представляют собой блоки статической памяти, размер которых должен определяться во время компиляции до запуска программы.

Инициализация (присвоение значений) массивов

Элементы в массиве могут быть явно инициализированы определенными значениями, когда они объявлены, путем включения этих начальных значений в фигурные скобки {}. Например:

int foo [5] = { 16, 2, 77, 40, 12071 }; 

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


количество значений между фигурными скобками {}не должно превышать число элементов в массиве. Например, в приведенном выше примере fooбыло объявлено 5 элементов (как указано числом, заключенным в квадратные скобки []), а фигурные скобки {}содержат ровно 5 значений, по одному для каждого элемента. Если объявлено с меньшим значением, остальные элементы устанавливаются в значения по умолчанию (что для основных типов означает, что они заполнены нулями). Например:

int bar [5] = { 10, 20, 30 }; 

Создает такой массив:


Инициализатор может даже не иметь значений, просто привязки:

int baz [5] = { }; 

Это создает массив из пяти intзначений, каждый из которых инициализируется нулевым значением.


Когда инициализация значений предоставляется для массива, C ++ позволяет оставлять квадратные скобки пустыми []. В этом случае компилятор автоматически примет размер массива, который соответствует числу значений, заключенных между фигурными скобками {}:

int foo [] = { 16, 2, 77, 40, 12071 };

После этого объявления массив fooбудет иметь intдлину 5 , так как мы предоставили 5 значений инициализации.

Наконец, эволюция C ++ привела к принятию универсальной инициализации также для массивов. Следовательно, больше нет необходимости в знаке равенства между объявлением и инициализатором. Оба эти утверждения эквивалентны:

int foo[] = { 10, 20, 30 };

int foo[] { 10, 20, 30 };

Доступ к значениям массива

К значениям любого из элементов в массиве можно получить доступ точно так же, как значение регулярной переменной того же типа. Синтаксис следующий:name[index]
После предыдущих примеров, в которых fooбыло 5 элементов, и каждый из этих элементов имел тип int, имя, которое может использоваться для обозначения каждого элемента, следующее:
Например, следующий оператор сохраняет значение 75 в третьем элемент foo:

foo [2] = 75;

и, например, следующее копирует значение третьего элемента fooпеременной x:

x = foo[2];

Следовательно, выражение foo[2]само по себе является переменной типа int.

Обратите внимание, что fooуказан третий элемент foo[2], так как первый из них foo[0], второй foo[1], и, следовательно, третий foo[2]. По этой же причине последний элемент foo[4]. Поэтому, если мы пишем foo[5], мы будем обращаться к шестому элементу fooи, следовательно, фактически превышать размер массива.

На этом этапе важно четко различать два использования скобок []связаны с массивами. Они выполняют две разные задачи: первая – указать размер массивов при их объявлении; а вторая – указывать индексы для конкретных элементов массива при их доступе.

1
2
int foo[5];         // объявление массива
foo[2] = 75;        // доступ к элементу массива 

Основное отличие состоит в том, что объявлению предшествует тип элементов, а в доступе – нет.

Некоторые другие действительные операции с массивами:

1
2
3
4
foo[0] = a;
foo[a] = 75;
b = foo [a+2];
foo[foo[a]] = foo[2] + 5;

Например:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Пример массива "Сумма элементов"
#include <iostream>
using namespace std;

int foo [] = {16, 2, 77, 40, 12071};
int n, result=0;

int main ()
{
  for ( n=0 ; n<5 ; ++n )
  {
    result += foo[n];
  }
  cout << result;
  return 0;
}
12206

result += foo[n]; // равнозначно result = result + foo[n]; в первом случае сокращенная запись

Многомерные массив

многомерный массив

Многомерные массивы можно охарактеризовать как «массивы массивов». Например, 
двумерный массив можно представить в виде двумерной таблицы, состоящей из 
элементов, одного и того же типа данных, с одним именем и разными индексами 
(типа "морского боя").


jimmyпредставляет собой двумерный массив 3 на 5, типа int. Синтаксис C ++ для объявления:

 
int jimmy [3][5];

способ ссылки на второй элемент по вертикали и четвертый по горизонтали в выражении:

 
jimmy[1][3]


(помните, что индексы массива всегда начинаются с нуля).

Присвоение значений в двумерном массиве:

#define WIDTH 5
#define HEIGHT 3
int jimmy [HEIGHT][WIDTH];
int n,m;

int main ()
{
  for (n=0; n<HEIGHT; n++)
     for (m=0; m<WIDTH; m++)
    {
        jimmy[n][m]=(n+1)*(m+1);
    }
}

Код не выводит массив на экране, но присваивают значения блоку памяти, называемому jimmy, следующим образом:


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

==================================================================

Массивы как параметры*

В какой-то момент нам может понадобиться передать массив функции в качестве параметра. В C ++ невозможно передать весь блок памяти, представленный массивом, функции непосредственно в качестве аргумента. Но то, что может быть принято, – это его адрес. На практике это имеет почти такой же эффект, и это намного быстрее и эффективнее.Чтобы принять массив как параметр для функции, параметры могут быть объявлены как тип массива, но с пустыми скобками, опуская фактический размер массива. Например:

 
void procedure (int arg[])

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

int myarray [40];

достаточно было бы написать такой вызов:

procedure (myarray);

Здесь у вас есть полный пример:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// arrays as parameters
#include <iostream>
using namespace std;

void printarray (int arg[], int length) {
  for (int n=0; n<length; ++n)
    cout << arg[n] << ' ';
  cout << '\n';
}

int main ()
{
  int firstarray[] = {5, 10, 15};
  int secondarray[] = {2, 4, 6, 8, 10};
  printarray (firstarray,3);
  printarray (secondarray,5);
}
5 10 15
2 4 6 8 10

В приведенном выше коде первый параметр ( int arg[]) принимает любой массив, элементы которого имеют тип int, независимо от его длины. По этой причине мы включили второй параметр, который сообщает функции длину каждого массива, который мы передаем ему в качестве первого параметра. Это позволяет циклу for печатать массив, чтобы знать диапазон для итерации в переданном массиве, не выходя за пределы диапазона.

В объявлении функции также можно включать многомерные массивы. Формат для трехмерного параметра массива:

base_type[][depth][depth]

Например, функция с многомерным массивом в качестве аргумента может быть:

void procedure (int myarray[][3][4])

Обратите внимание, что первые скобки []оставлены пустыми, а следующие определяют размеры для соответствующих размеров. Это необходимо для того, чтобы компилятор мог определить глубину каждого дополнительного измерения.

В некотором смысле передача массива как аргумента всегда теряет измерение. Причина в том, что по историческим причинам массивы не могут быть скопированы напрямую, и, следовательно, то, что действительно передается, является указателем. Это общий источник ошибок для начинающих программистов. Хотя ясное понимание указателей, объясняемое в грядущей главе, очень помогает.

 

Библиотечные массивы

Рассмотренные выше массивы непосредственно реализуются как языковая функция, унаследованная от языка C. Это отличная функция, но, ограничивая ее копию и легко распадаясь на указатели, они, вероятно, страдают от избытка оптимизации.Чтобы преодолеть некоторые из этих проблем с помощью встроенных в язык массивов, C ++ предоставляет альтернативный тип массива в качестве стандартного контейнера. Это шаблон типа (фактически шаблон шаблона), определенный в заголовке <array>.Контейнеры представляют собой библиотечную функцию, выходящую за рамки данного руководства, и, следовательно, этот класс не будет подробно описан здесь. Достаточно сказать, что они работают аналогично встроенным массивам, за исключением того, что они позволяют копировать (фактически дорогостоящая операция, которая копирует весь блок памяти и, следовательно, будет использоваться с осторожностью) и распадаться на указатели только тогда, когда явно сказал сделать это (через своего члена data).Как пример, это две версии одного и того же примера с использованием встроенного в язык массива, описанного в этой главе, и контейнера в библиотеке:

встроенный язык контейнерная библиотека

#include <iostream>

using namespace std;

int main()
{
  int myarray[3] = {10,20,30};

  for (int i=0; i<3; ++i)
    ++myarray[i];

  for (int elem : myarray)
    cout << elem << '\n';
}

#include <iostream>
#include <array>
using namespace std;

int main()
{
  array<int,3> myarray {10,20,30};

  for (int i=0; i<myarray.size(); ++i)
    ++myarray[i];

  for (int elem : myarray)
    cout << elem << '\n';
}

Как вы можете видеть, оба вида массивов используют один и тот же синтаксис для доступа к его элементам: myarray[i]. Помимо этого, основные отличия заключаются в объявлении массива и включении дополнительного заголовка для массива библиотеки . Обратите внимание также, как легко получить доступ к размеру массива библиотеки .

Залишити відповідь