инициализатор: = выражение = (* список_инициализаторов , opt *) ( список_выражений ) список_инициализаторов: выражение список_инициализаторов , список_инициализаторов (* список_инициализаторов *)
Все выражения в инициализаторе статической или внешней переменной должны быть константными выражениями, которые опсаны в #12, или выражениями, которые сводятся к адресам ранее описанных переменных, возможно со смещением на константное выражение. Автоматические и регистровые переменные могут инциализироваться любыми выражениями, включащими константы, рнее описанные переменные и функции.
Гарантируется, что неинициализированные статические и внешние переменные получают в качестве начального значения 0. Гарантируется, что неинициализированные автоматические и ргистровые переменные получают в качестве начального значения «пустое место»*.
– * В английском – «garbage», означающее затертое место [памяти], т.е. если переменная целая, то 0, если char, то ' ', если указатель на Т, то (Т*) NULL. (прим. перев.)
Когда инициализатор применяется к скаляру (указатель или объект арифметического типа), он состоит из одного выражения, возможно, заключенного в фигурные скобки. Начальное значение объекта находится из выражения; выполняются те же преобразвания, что и при присваивании.
Заметьте, что поскольку () не является инициализатором, то X a(); является не описанием объекта класса X, а описанием функции, не получающей значений и возвращающей X.
8.6.1 Список Инициализаторов
Когда описанная переменная является составной (класс или массив), то инициализатор может состоять из заключенного в фигурные скобки, разделенного запятыми списка инициализаторов для членов составного объекта, в порядке возрастания индекса или по порядку членов. Если массив содерхит составные подобекты, то это правило рекурсивно применяется к членам состаного подобъекта. Если инициализаторов в списке меньше, чем членов в составном подобъекте, то составной подобъект допоняется нулями.
Фигурные скобки могут опускаться следующим образом. Если инициализатор начинается с левой фигурной скобки, то следущий за ней список инициализаторов инициализирует члены сотавного объекта; наличие числа инициализаторов, большего, чем число членов, считается ошибочным. Если, однако, инициализтор не начинается с левой фигурной скобки, то из списка брутся только элементы, достаточные для сопоставления элеметам составного объекта; все остающиеся элементы оставляются для инициализации следующего элемента составного объекта, частью которого является текущий составной объект.
Например,
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] инициализируется 0-ями. В тоноcти тот же эффект может быть достигнут с помощью
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 (рассматриваемого как двумерный массив) и оставляет остальные элементы нулями.
8.6.2 Объекты Классов
Объект с закрытыми членами не может быть инициализован списком инициализаторов; это же относится к объекту объединние. Объект класса с конструктором должен инициализироваться. Если класс имеет конструктор, не получающий параметров, то этот конструктор используется для объектов, которые явно не инициализированы. Список параметров для конструктора можно добавлять к имени в описании или к типу в выражении new. Слдующие инициализации все дают одно и тоже значение (#8.4): struct complex (*
float re; float im; complex (float r,float i = 0) (* re=r; im=i; *) *);
complex zz1(1,0); complex zz2(1); complex* zp1 = new complex (1,0); complex* zp1 = new complex (1);
Объекты класса могут также инициализироваться с помощью явного использования операции =. Например:
complex zz3 = complex (1,0); complex zz4 = complex (1); complex zz5 = 1; complex zz6 = zz3;
Если есть конструктор, получающий ссылку на объект свого собственного класса, то он будет вызываться при инициалзации объекта другим объектом этого класса, но не при иницилизации объекта конструктором.
Объект может быть членом составного объекта только (1) если класс объекта не имеет конструктора, или (2) если его конструкторы не имеют параметров, или (3) если составной обект является классом с конструктором, который задает список инициализации члена (см. #10). В случае 2 конструктор вызывется при создании составного объекта. Если составной объект является классом (но не тогда, когда он является вектором) для вызова конструктора могут использоваться параметры по умолчанию. Если член составного объекта является членом класа с деструкторами, то этот деструктор вызывается при уничтжении составного объекта.
Конструкторы для нелокальных статических объектов вызваются в порядке их появления в файле; деструкторы для вызываются в обратном порядке. Вызывается ли конструктор или деструктор для локального статического объекта в случае если функция, в которой объект описан, не вызывается, не определно. Если конструктор для локального статического объекта взывается, то он вызывается после конструкторов для глобальных объектов, лексически ему предшествующих. Если для локального статического объекта вызывается деструктор, то он вызывается до деструкторов для глобальных объектов, лексически ему прешествующих.
8.6.3 Ссылки
Когда переменная описана как T amp;, то есть «ссылка на тип T», она должна быть инициализирована или объектом типа T, или объектом объектом, который может быть преобразован в T. Ссыка становится другим именем объекта. Например:
int i; int amp; r = i; r = 1; // значение i становится 1 int* p = amp;r; // p указывает на i
Значение ссылки не может быть изменено после инициализции. Заметьте, что обработка инициализации ссылки очень силно зависит от того, что ей присваивается. Если инициализатор для ссылки на тип T не является lvalue, то будет создан и инициализован инициализатором обект типа T. Тогда ссылка станет именем для этого объекта. Время жизни объекта, созданного таким способом, будет область видимости, в которой он создан. Например:
double amp; rr = 1;
допустимо, и rr будет указывать на объект типа double, содержащий значение 1.0.
Заметьте, что ссылка на класс B может быть инициализирвана объектом класса D при условии, что B является открытым базовым классом класса D (в этом случае D есть B).
Ссылки особенно полезны в качестве типов параметров. Например:
struct B (* ... *); struct D : B (* ... *); int f(B amp;); D a; f(a);
8.6.4 Массивы Символов
Массив char можно инициализировать строкой. Последовтельные символы строки инициализируют члены массива. Напрмер:
char msg[] = «Syntax error on line %d »;
демонстрирует массив символов, члены которого инициалзированы строкой. Обратите внимание, что sizeof(msg)==25.