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

Инициализация многомерных массивов

Значения элементов многомерного массива, как и в одномерном случае, могут быть заданы константными значениями при объявлении, заключенными в фигурные скобки {}. Однако в этом случае указание количества элементов в строках и столбцах должно быть обязательно указано в квадратных скобках [].Пример на Си


123456789

#include <stdio.h>int main(){  int a = { 1, 2, 3, 4, 5, 6 };  printf(«%d %d %d\n», a, a, a);  printf(«%d %d %d\n», a, a, a);  getchar();  return 0;}

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

123456789101112131415161718192021222324252627

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>int main(){  int a; // массив из 2 строк и 3 столбцов  int i, j;  // Ввод элементов массива  for (i = 0; i<2; i++)  // цикл по строкам  {    for (j = 0; j<3; j++) // цикл по столбцам    {      printf(«a = «, i, j);      scanf(«%d», &a);    }  }  // Вывод элементов массива  for (i = 0; i<2; i++)  // цикл по строкам  {    for (j = 0; j<3; j++) // цикл по столбцам    {      printf(«%d «, a);    }    printf(«\n»); // перевод на новую строку  }  getchar(); getchar();  return 0;}

Классика жанра

Если мы откроем классический труд «Язык программирования C» Брайана Кернигана и Денниса Ритчи, то прочитаем, что «В языке C есть возможность работать с многомерными прямоугольными массивами, хотя на практике они используются гораздо реже, чем массивы указателей». C++ практически полностью унаследовал работу с многомерными массивами своего предтечи.

Определение автоматических многомерных массивов

В этом разделе я буду иногда употреблять термин «матрица» как синоним термина «двумерный массив». В C/C++ прямоугольный двумерный массив чисел действительно реализует математическое понятие «матрица». Однако, в общем случае, двумерный массив — понятие гораздо более широкое, чем матрица, поскольку он может быть и не прямоугольным, и не числовым.

Определение автоматических многомерных массивов почти полностью совпадает с определением одномерных массивов (о чём было рассказано в первой статье), за исключением того, что вместо одного размера может быть указано несколько:

В этом примере определяется двумерный массив из 3 строк по 5 значений типа в каждой строке. Итого 15 значений типа .

Во втором примере определяется трёхмерный массив, содержащий 3 матрицы, каждая из которых состоит из 5 строк по 2 значения типа в каждой строке.

Понятно, что тип данных, содержащихся в многомерном массиве, может быть любым.

При дальнейшем изложении для таких многомерных массивов будет употребляться термин «C-массив», что бы отличать их от массивов других видов.

Инициализация

При статической (определяемой на этапе компиляции) инициализации значения C-массива перечисляются в порядке указания размеров (индексов) в определении массива. Каждый уровень (индекс), кроме самого младшего, многомерного массива заключается в свою пару фигурных скобок. Значения самого младшего индекса указываются через запятую:

В примере показана статическая инициализация прямоугольного массива. Весь список инициализирующих значений заключён в фигурные скобки. Значения для каждой из 3 строк заключены в свою пару из фигурных скобок, значения для каждого из 5 столбцов для каждой строки перечислены через запятую.

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

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

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

В этом примере каждому элементу массива присваивается значение, первая цифра которого указывает номер строки, а вторая цифра — номер столбца для этого значения (нумерация с 1).

Вывод значений массива на консоль

В продолжение предыдущего примера можно написать:

В результате получим следующий вывод на консоль:

Для трёхмерного массива можно написать код, использующий те же приёмы:

Здесь присваивание значения элементу массива и вывод на консоль происходят в одной группе циклов.

Расположение в памяти

Для многомерного C-массива выделяется единый блок памяти необходимого размера: .

Значения располагаются последовательно. Самый левый индекс изменяется медленнее всего. Т.е. для трёхмерного массива сначала располагаются значения для первой (индекс 0) матрицы, затем для второй и т.д. Значения для матриц располагаются построчно (ср. со статической инициализацией массива выше).

Имя (идентификатор) многомерного C-массива является указателем на первый элемент массива (так же как и для одномерных массивов)

Если код из последнего примера немного изменить:

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

№1

Поскольку все значения многомерного C-массива располагаются последовательно, то, пользуясь адресной арифметикой, можно сделать следующий хак:

Или даже так:

В последнем фрагменте осуществляется доступ к значениям двумерного массива как к одномерному массиву. Цивилизованное решение реализуется через .

№2

Из двух примеров, приведённых выше, следует, что работу с двумерным или многомерным массивом (в понимании на более высоком уровне абстракции) технически можно организовать посредством одномерного массива соответствующего размера:

Этот приём достаточно распространён. Его выгода в том, что массив не обязательно должен быть выделен автоматически. Его можно выделять и динамически. Но при этом логически рассматривать как C-массив.

Вышеприведённый код написан в духе чистого C. В C++ обычно такие вещи прячут в класс, оставляя снаружи лаконичный интерфейс без всяких следов адресной арифметики.

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

В языке Си могут быть также объявлены многомерные массивы. Отличие многомерного массива от одномерного состоит в том, что в одномерном массиве положение элемента определяется одним индексом, а в многомерном — несколькими. Примером многомерного массива является матрица. Общая форма объявления многомерного массива

  тип имя…;

int a;

Общее количество элементов в приведенном двумерном массиве определится как

КоличествоСтрок * КоличествоСтолбцов = 2 * 3 = 6.

Количество байт памяти, требуемых для размещения массива, определится как

КоличествоЭлементов * РазмерЭлемента = 6 * 4 = 24 байта.

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

Обработку массивов удобно организовывать с помощью специальных функций. Для обработки массива в качестве аргументов функции необходимо передать

  • адрес массива,
  • размер массива.

  Исключение составляют функции обработки строк, в которые достаточно передать только адрес. При передаче переменные в качестве аргументов функции данные передаются как копии. Это означает, что если внутри функции произойдет изменение значения параметра, то это никак не повлияет на его значение внутри вызывающей функции. Если в функцию передается адрес переменной (или адрес массива), то все операции, выполняемые в функции с данными, находящимися в пределах видимости указанного адреса, производятся над оригиналом данных, поэтому исходный массив (или значение переменной) может быть изменено вызываемой функцией.Пример на Си Дан массив из 10 элементов. Поменять местами наибольший и начальный элементы массива. Для операций поиска максимального элемента и обмена использовать функцию.

123456789101112131415161718192021222324252627282930313233343536373839404142

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>// Функция обменаvoid change(int *x, int n){  // x — указатель на массив (адрес массива)  // n — размер массива  int i;  int max, index;  max = x;  index = 0;  // Поиск максимального элемента  for (i = 1; i<n; i++)  {    if (x>max)    {      max = x;      index = i;    }  }  // Обмен  x = x;  x = max;}// Главная функцияint main(){  int a;  int i;  for (i = 0; i<10; i++)  {    printf(«a = «, i);    scanf(«%d», &a);  }  change(a, 10);  // вызов функции обмена          // Вывод элементов массива  for (i = 0; i<10; i++)    printf(«%d «, a);  getchar();  getchar();  return 0;}

12345678910111213141516171819202122232425262728293031

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>// Функция вычисления произведения чётных элементовint func(int *x, int n)  // произведение четных элементов{  int p = 1;  // начальное значение произведения  int i;  for (i = 0; i<n; i++)   {    if (x % 2 == 0)  // остаток от деления на 2 равен 0?      p = p * x;  }  return p;}// Главная функцияint main() {  int a; // объявлен массив a из 5 элементов  int i;  int pr;  // Ввод элементов массива  for (i = 0; i<5; i++)   {    printf(«a = «, i);    scanf(«%d», &a); // &a — адрес i-го элемента массива  }  pr = func(a, 5); // вычисление произведения  printf(«\n pr = %d», pr); // вывод произведения четных элементов  getchar();   getchar();  return 0;}

Язык Си

reduce/reduceRight

Метод «arr.reduce(callback)» используется для последовательной обработки каждого элемента массива с сохранением промежуточного результата.

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

Метод используется для вычисления на основе массива какого-либо единого значения, иначе говорят «для свёртки массива». Чуть далее мы разберём пример для вычисления суммы.

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

Аргументы функции :

  • – последний результат вызова функции, он же «промежуточный результат».
  • – текущий элемент массива, элементы перебираются по очереди слева-направо.
  • – номер текущего элемента.
  • – обрабатываемый массив.

Кроме , методу можно передать «начальное значение» – аргумент . Если он есть, то на первом вызове значение будет равно , а если у нет второго аргумента, то оно равно первому элементу массива, а перебор начинается со второго.

Проще всего понять работу метода на примере.

Например, в качестве «свёртки» мы хотим получить сумму всех элементов массива.

Вот решение в одну строку:

Разберём, что в нём происходит.

При первом запуске – исходное значение, с которого начинаются вычисления, равно нулю (второй аргумент ).

Сначала анонимная функция вызывается с этим начальным значением и первым элементом массива, результат запоминается и передаётся в следующий вызов, уже со вторым аргументом массива, затем новое значение участвует в вычислениях с третьим аргументом и так далее.

Поток вычислений получается такой

В виде таблицы где каждая строка – вызов функции на очередном элементе массива:

результат
первый вызов
второй вызов
третий вызов
четвёртый вызов
пятый вызов

Как видно, результат предыдущего вызова передаётся в первый аргумент следующего.

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

Посмотрим, что будет, если не указать в вызове :

Результат – точно такой же! Это потому, что при отсутствии в качестве первого значения берётся первый элемент массива, а перебор стартует со второго.

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

Метод arr.reduceRight работает аналогично, но идёт по массиву справа-налево.

Добавление/удаление элементов

Мы уже знаем методы, которые добавляют и удаляют элементы из начала или конца:

  • – добавляет элементы в конец,
  • – извлекает элемент из конца,
  • – извлекает элемент из начала,
  • – добавляет элементы в начало.

Есть и другие.

Как удалить элемент из массива?

Так как массивы – это объекты, то можно попробовать :

Вроде бы, элемент и был удалён, но при проверке оказывается, что массив всё ещё имеет 3 элемента .

Это нормально, потому что всё, что делает – это удаляет значение с данным ключом . Это нормально для объектов, но для массивов мы обычно хотим, чтобы оставшиеся элементы сдвинулись и заняли освободившееся место. Мы ждём, что массив станет короче.

Поэтому для этого нужно использовать специальные методы.

Метод arr.splice(str) – это универсальный «швейцарский нож» для работы с массивами. Умеет всё: добавлять, удалять и заменять элементы.

Его синтаксис:

Он начинает с позиции , удаляет элементов и вставляет на их место. Возвращает массив из удалённых элементов.

Этот метод проще всего понять, рассмотрев примеры.

Начнём с удаления:

Легко, правда? Начиная с позиции , он убрал элемент.

В следующем примере мы удалим 3 элемента и заменим их двумя другими.

Здесь видно, что возвращает массив из удалённых элементов:

Метод также может вставлять элементы без удаления, для этого достаточно установить в :

Отрицательные индексы разрешены

В этом и в других методах массива допускается использование отрицательного индекса. Он позволяет начать отсчёт элементов с конца, как тут:

Метод arr.slice намного проще, чем похожий на него .

Его синтаксис:

Он возвращает новый массив, в который копирует элементы, начиная с индекса и до (не включая ). Оба индекса и могут быть отрицательными. В таком случае отсчёт будет осуществляться с конца массива.

Это похоже на строковый метод , но вместо подстрок возвращает подмассивы.

Например:

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

Метод arr.concat создаёт новый массив, в который копирует данные из других массивов и дополнительные значения.

Его синтаксис:

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

В результате мы получаем новый массив, включающий в себя элементы из , а также , и так далее…

Если аргумент – массив, то все его элементы копируются. Иначе скопируется сам аргумент.


Например:

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

…Но если объект имеет специальное свойство , то он обрабатывается как массив: вместо него добавляются его числовые свойства.

Для корректной обработки в объекте должны быть числовые свойства и :

Объявление и инициализация массивов

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

тип имя={инициализация};

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

int a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};  // массив a из 10 целых чисел

int b = {0}; // массив b из 10 элементов, инициализированных 0

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

int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};

[]Пример на Си

12345678

#include <stdio.h>int main(){  int a[] = { 5, 4, 3, 2, 1 }; // массив a содержит 5 элементов  printf(«%d %d %d %d %d\n», a, a, a, a, a);  getchar();  return 0;}

Однако часто требуется задавать значения элементов массива в процессе выполнения программы. При этом используется объявление массива без инициализации. В таком случае указание количества элементов в квадратных скобках обязательно.

int a;

123456789101112131415161718

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>int main(){  int a; // объявлен массив a из 5 элементов  int i;  // Ввод элементов массива  for (i = 0; i<5; i++)   {    printf(«a = «, i);    scanf(«%d», &a); // &a — адрес i-го элемента массива  }  // Вывод элементов массива  for (i = 0; i<5; i++)    printf(«%d «, a); // пробел в формате печати обязателен  getchar(); getchar();  return 0;}

Размер массива

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

printf("Enter length of array ");
scanf("%d", &length);

{
	float x;
}

Создание динамических массивов будет рассмотрено дальше, при работе с указателями и памятью

В некоторых случаях можно узнать размер массива с помощью функции sizeof.

#include <conio.h>
#include <stdio.h>

void main() {
	int A;
	//sizeof возвращает размер всего массива в байтах
	//Для определения количества элементов необходимо
	//разделить размер массива на размер его элемента
	int size = sizeof(A) / sizeof(int);

	printf("Size of array equals to %d", size);
	getch();
}

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

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

Пример двумерного массива

Рассмотрим пример использования двумерного массива:

#include <iostream> int main() { // Объявляем массив 10×10 const int numRows = 10; const int numCols = 10; int product = { 0 }; // Создаем таблицу умножения for (int row = 0; row < numRows; ++row) for (int col = 0; col < numCols; ++col) product = row * col; // Выводим таблицу умножения for (int row = 1; row < numRows; ++row) { for (int col = 1; col < numCols; ++col) std::cout << product << «\t»; std::cout << ‘\n’; } return 0; }

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

#include <iostream>

intmain()

{

// Объявляем массив 10×10

constintnumRows=10;

constintnumCols=10;

intproductnumRowsnumCols={};

// Создаем таблицу умножения

for(introw=;row<numRows;++row)

for(intcol=;col<numCols;++col)

productrowcol=row *col;

// Выводим таблицу умножения

for(introw=1;row<numRows;++row)

{

for(intcol=1;col<numCols;++col)

std::cout<<productrowcol<<«\t»;

std::cout<<‘\n’;

}

return;

}

Эта программа вычисляет и выводит таблицу умножения от 1 до 9 (включительно)

Обратите внимание, при выводе таблицы в цикле for мы начинаем с 1 вместо 0. Это делается с целью предотвращения вывода нулевой строки и нулевого столбца, содержащих одни нули!

Результат выполнения программы:

Двумерные массивы обычно используются в играх типа tile-based, где каждый элемент массива представляет собой один фрагмент/плитку. Они также используются в компьютерной 3D-графике (в виде матриц) для вращения, масштабирования и отражения фигур.

Объявление

Существует два варианта синтаксиса для создания пустого массива:

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

Элементы массива нумеруются, начиная с нуля.

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

Мы можем заменить элемент:

…Или добавить новый к существующему массиву:

Общее число элементов массива содержится в его свойстве :

Вывести массив целиком можно при помощи .

В массиве могут храниться элементы любого типа.

Например:

Висячая запятая

Список элементов массива, как и список свойств объекта, может оканчиваться запятой:

«Висячая запятая» упрощает процесс добавления/удаления элементов, так как все строки становятся идентичными.

Инициализация двумерных массивов

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

int array = { { 1, 2, 3, 4, 5 }, // строка №0 { 6, 7, 8, 9, 10 }, // строка №1 { 11, 12, 13, 14, 15 } // строка №2 };

1 2 3 4 5 6

intarray35=

{

{1,2,3,4,5},// строка №0

{6,7,8,9,10},// строка №1

{11,12,13,14,15}// строка №2

};


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

int array = { { 2, 4 }, // строка №0 = 2, 4, 0, 0, 0 { 1, 3, 7 }, // строка №1 = 1, 3, 7, 0, 0 { 8, 9, 11, 12 } // строка №2 = 8, 9, 11, 12, 0 };

1 2 3 4 5 6

intarray35=

{

{2,4},// строка №0 = 2, 4, 0, 0, 0

{1,3,7},// строка №1 = 1, 3, 7, 0, 0

{8,9,11,12}// строка №2 = 8, 9, 11, 12, 0

};

В двумерном массиве со списком инициализаторов можно не указывать только левый индекс (длину массива):

int array[] = { { 1, 2, 3, 4, 5 }, { 6, 7, 8, 9, 10 }, { 11, 12, 13, 14, 15 } };

1 2 3 4 5 6

intarray5=

{

{1,2,3,4,5},

{6,7,8,9,10},

{11,12,13,14,15}

};

Компилятор может сам вычислить количество строк в массиве. Однако не указывать два индекса — это уже ошибка:

int array[][] = { { 3, 4, 7, 8 }, { 1, 2, 6, 9 } };

1 2 3 4 5

intarray=

{

{3,4,7,8},

{1,2,6,9}

};

Подобно обычным массивам, многомерные массивы можно инициализировать значением следующим образом:

int array = { 0 };

1 intarray35={};

Обратите внимание, это работает только в том случае, если вы явно объявляете длину массива (указываете левый индекс)! В противном случае, вы получите двумерный массив с 1 строкой

Описание синтаксиса

Массив создается почти так же, как и обычная переменная. Для хранения десяти фамилий нам нужен массив, состоящий из 10 элементов. Количество элементов массива задается при его объявлении и заключается в квадратные скобки.

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

Попробуем вывести наш массив на экран с помощью оператора .

Скомпилируйте этот код и посмотрите, на результат работы программы. Готово? А теперь запустите программу еще раз и сравните с предыдущим результатом. В моей операционной системе вывод был следующим:

  • Первый вывод:
  • Второй вывод:
  • Третий вывод:

Мы видим, что выводится адрес этого массива в оперативной памяти, а никакие не «Иванов» и «Петров».

Дело в том, что при создании переменной, ей выделяется определенное место в памяти. Если мы объявляем переменную типа , то на машинном уровне она описывается двумя параметрами — ее адресом и размером хранимых данных.

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

Попробуем вывести первый элемент массива — фамилию студента Иванова.

Смотрим, компилируем, запускаем. Убедились, что вывелся именно «Иванов». Заметьте, что нумерация элементов массива в C++ начинается с нуля. Следовательно, фамилия первого студента находится в , а фамилия последнего — в .

В большинстве языков программирования нумерация элементов массива также начинается с нуля.

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

3.2. Синтаксис инициализации массивов

3.2.1. Общие положения

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

Со времен C массивы можно было инициализировать с помощью синтаксиса агрегатной инициализации:

В С++11 появилась универсальная инициализация (uniform initialization) и теперь можно инициализировать так:

Для универсальной инициализации также можно использовать =, и различать эти два типа инициализации не всегда просто, а, скорее всего, не очень нужно.

Размер массива можно не указывать, тогда он определится по числу инициализаторов.

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

Массивы констант тривиального типа требуют обязательного списка инициализации.

Число инициализаторов может быть меньше размера массива, в этом случае оставшиеся элементы инициализируются конструктором по умолчанию.

Символьные массивы можно инициализировать строковым литералом.

Размер такого массива будет на единицу больше числа символов строки, нужно хранить завершающий нулевой символ.

3.2.2. Инициализация членов класса

В С++11 появилась возможность инициализировать массивы, являющиеся нестатическими членами класса. Это можно сделать двумя способами: непосредственно при объявлении или в списке инициализации членов при определении конструктора.

Правда в этом случае надо всегда явно задавать размер массива, неявное определение размера через список инициализации не разрешается.

Статические массивы, как и ранее, можно инициализировать только при определении, размер массива может быть определен через список инициализации.

3.2.3. Требования к инициализаторам

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

или

Наличие нужного преобразования эквивалентно корректности инструкции

Элемент списка инициализации может быть сам списком инициализации. В этом случае корректность этой инструкции также гарантирует корректную инициализацию элемента массива.

Рассмотрим пример.

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

Этот пример также демонстрирует как с помощью списка инициализации мы можем создать массив для типа у которого нет конструктора по умолчанию. Но в этом случае число инициализаторов должно совпадать с размером массива.


С этим читают