Гарантируется, что переменные статического класса памяти (§R.3.5), которые не были инициализированы, в качестве начального значения получат 0, приведенный к нужному типу. То же справедливо для статических членов объектов класса. Начальные значения автоматических и регистровых переменных, которые не были инициализированы, неопределены.
Если инициализатор относится к указателю или объекту арифметического типа, он состоит из одного выражения (возможно в скобках). В качестве начального значения объекта берется значение выражения, происходят такие же преобразования типа, как и в случае присваивания.
Заметим, что поскольку () не является инициализатором, описание
X a();
задает не объект a типа класс X, а является описанием функции без параметров, возвращающей X.
Инициализатор для статического члена принадлежит области видимости члена класса, например,
int a;
struct X {
static int a;
static int b;
};
int X::a = 1;
int X::b = a; // X::b = X::a
Агрегатом называется массив или объект типа класс (§R.9), не имеющий конструкторов (§R.12.1), частных или защищенных членов (§R.11), базовых классов (§R.10) и виртуальных функций (§R.10.2). Если агрегат инициализируется, то инициализатором должен быть список-инициализаторов, который состоит из заключенного в фигурные скобки списка, разделенного запятыми, инициализаторов для членов агрегата. Инициализаторы идут в возрастающем порядке индексов или членов агрегата. Если агрегат содержит вложенные агрегаты, это правило применяется рекурсивно для членов вложенных агрегатов. Если инициализаторов в списке меньше, чем членов агрегата, то он дополняется нулевыми значениями соответствующих типов.
Например, в следующем фрагменте
struct S {int a; char* b; int c;}
S ss = {1, "asdf"};
ss.a инициализируется значением 1, ss.b - "asdf", а ss.c - 0.
Кроме того, агрегат, являющийся классом, можно инициализировать объектом этого класса или класса, являющегося общим производным от него (§R.12.8).
Фигурные скобки разбираются следующим образом. Если список-инициализаторов начинается левой фигурной скобкой, то список инициализаторов, разделенных запятыми, задает значения членам агрегата, причем считается ошибкой, если инициализаторов больше, чем членов. Иначе, если список-инициализаторов или вложенный агрегат не начинается левой фигурной скобкой, то из списка используется такое число элементов, которое нужно для инициализации членов текущего агрегата; все оставшиеся элементы используются для инициализации членов следующего агрегата, в который вложен текущий агрегат.
Например, в определении
int x[] = {1, 3, 5};
массив x инициализируется как одномерный массив из трех элементов, поскольку размер массива не указан, и приведено три инициализатора.
Приведем пример инициализации с полной скобочной структурой.
float y[4][3] = {
{1, 3, 5},
{2, 4, 6},
{3, 5, 7},
};
Здесь значения 1, 3, 5 инициализируют первую строку массива y[0], т.е. y[0][0], y[0][1] и y[0][2]. Аналогично, следующие две строки инициализируют y[1] и y[2]. Инициализаторы приведены не полностью, поэтому y[3] инициализируется нулями. Точно такого же результата можно достичь с помощью такой инициализации:
float y[4][3] = {
1, 3, 5, 2, 4, 6, 3, 5, 7,
};
Последний (самый правый) индекс изменяется быстрее всего.
В последнем примере инициализатор для y начинается левой фигурной скобкой, но для y[0] скобки не задано, поэтому из списка используется три элемента, также по три последовательных элемента используется для y[1] и y[2]. В следующем примере
float y[4][3] = {
{1}, {2}, {3}, {4}
};
инициализируется первый столбец y (который рассматривается как двумерный массив), а остальные столбцы принимают значение 0.
Инициализация массива объектов типа класс с помощью конструкторов описывается в §R.12.6.1.
Инициализатор для объединения без конструктора должен быть или отдельным выражением типа объединения, или заключенным в фигурные скобки, инициализатором первого члена объединения, например,
union u {i nt a; char* b; };
u a = {1};
u b = a;
u c = 1; // ошибка
u d = {0, "asdf"}; // ошибка
u e = {"asdf"}; // ошибка
Число инициализаторов не должно превышать числа членов или элементов, которые инициализируются. Например, следующая инициализация ошибочна:
char cv[4] = {'a', 's', 'd', 'f', 0}; // ошибка
Читать дальше