Автоматические, регистровые, статические и внешние переменные можно
инициализировать произвольными выражениями, содержащими константы и
описанные ранее переменные и функции. int f(int); int a = 2; int b = f(a); int c(b);
Указатель типа const T*, т.е. указатель на константу T, может инициализироваться
указателем типа T*, но инициализация для указателей в обратном порядке незаконна.
Объекты типа T можно инициализировать объектами типа T независимо от
использования спецификаций const или volatile в типах инициализируемой
переменной или инициализатора, например, int a; const int b = a; int c = b; const int*
p0 = &a; const int* p1 = &b; int* p2 = &b; // ошибка: указатель без const //
настраивается на объект const int *const p3 = p2; int *const p4 = p1; // ошибка:
указатель без const // настраивается на объект const const int* p5 = p1; Здесь причина
обеих ошибок одна: если допустить подобную инициализацию, она позволит изменять
с помощью указателя без соответствующей спецификации значение чего-то, что было
описано как const. На выражения для стандартных значений параметров
накладывается больше ограничений, см. $$R.8.2.6. Инициализация объектов классов с
помощью конструкторов описывается в $$R.12.6.1. Копирование объектов классов
описывается в $$R.12.8. Порядок инициализации статических объектов определяется
в $$R.3.4 и $$R.6.7. Гарантируется, что переменные статического класса памяти ($
$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.8.4.1 Агрегат
Агрегатом называется массив или объект типа класс ($$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 инициализируется как одномерный массив из трех элементов, поскольку
размер массива не указан, и приведено три инициализатора. Приведем пример
инициализации с полной скобочной структурой. loat 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] инициализируется нулями.
Точно такого же результата можно достичь с помощью такой инициализации: loat
y[4][3] = { 1, 3, 5, 2, 4, 6, 3, 5, 7, }; Последний (самый правый) индекс изменяется