Инициализаторы (Initializers)

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

инициализатор :
присваиваемоевыражение
{список-инициализаторов}
{список-инициализаторов , }

список-инициализаторов :
инициализатор
список-инициализаторов, инициализатор

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

Присваиваемоевыражение в инициализаторе должно быть того же типа, что и объект, который он инициализирует, или тип, который может быть преобразован в тип объекта в соответствии с разделом 4.1.10 «Неявные преобразования». Поскольку они включают конструкторы, составная переменная может быть инициализирована либо конструктором, либо списком инициализаторов; элемент в списке инициализаторов может быть конструктором.

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

int i = { 1 }; // нельзя, i не составная переменная

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

Если составная переменная имеет векторный тип, инициализаторы из списка применяются к компонентам вектора начиная с 0. Количество инициализаторов должно соответствовать количеству компонентов.

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

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

mat2x2 a = mat2( vec2( 1.0, 0.0 ), vec2( 0.0, 1.0 ) );
mat2x2 b = { vec2( 1.0, 0.0 ), vec2( 0.0, 1.0 ) };
mat2x2 c = { { 1.0, 0.0 }, { 0.0, 1.0 } };

Следующие примеры приведут к ошибке времени компиляции:

float a[2] = { 3.4, 4.2, 5.0 }; 
vec2 b = { 1.0, 2.0, 3.0 }; 
mat3x3 c = { vec3(0.0), vec3(1.0), vec3(2.0), vec3(3.0) }; 
mat2x2 d = { 1.0, 0.0, 0.0, 1.0 }; // не сможет распределить переменные
struct {
 float a;
 int b;
} e = { 1.2, 2, 3 };

Во всех случаях, самый глубоко вложенный инициализатор (т.е. не список инициализаторов, заключенных в фигурные скобки) применяемый к объекту должен иметь тот же тип, что и инициализируемый объект, или тип, который может быть преобразован в нужный в соответствии с разделом 4.1.10, «Неявные преобразования». В последнем случае неявное преобразование будет выполнено на инициализаторе до того, как будет выполнено присвоение.

mat2x2 a = mat2( vec2( 1.0, 0.0 ), vec2( 0.0, 1.0 ) );
mat2x2 b = { vec2( 1.0, 0.0 ), vec2( 0.0, 1.0 ) };
mat2x2 c = { { 1.0, 0.0 }, { 0.0, 1.0 } };

Следующие примеры приведут к ошибке времени компиляции:

struct {
 float a;
 int b;
} e = { 1.2, 2 }; // все типы соответствуют
struct {
 float a;
 int b;
} e = { 1, 3 }; // первый инициализатор преобразован

Все следующие объявления приводят к ошибке времени компиляции.

int a = true; 
vec4 b[2] = { vec4(0.0), 1.0 }; 
mat4x2 c = { vec3(0.0), vec3(1.0) }; 
struct S1 {
 vec4 a;
 vec4 b;
};
struct {
 float s;
 float t;
} d[] = { S1(vec4(0.0), vec4(1.1)) };

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

float a[] = float[](3.4, 4.2, 5.0, 5.2, 1.1);
float b[] = { 3.4, 4.2, 5.0, 5.2, 1.1 };
float c[] = a; // c имеет явный размер 5
float d[5] = b; // означает то же самое

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

Main Admin

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *