Переменные¶
Переменную можно объявить так:
var i32 x= 0;
Можно объявить сразу несколько переменных одного типа:
var i32 x= 0, y= 1, z= 2;
Модификаторы ссылки и изменяемости задаются индивидуально для каждой переменной:
var i32 mut a= 0, imut b= 0;
var i32 &mut a_ref= a, &imut b_ref= b, & b_ref2= b, imut y= 66, mut z= -56;
Ссылки¶
Модификатор ссылочности &
указывает, что переменная будет являться ссылкой.
Это значит, что ссылочная переменная будет ссылаться на значение какой-то другой переменной.
Изменение ссылочной переменной приведёт к изменению исходной переменной.
Объявление ссылки не создаёт копию значения, что может быть полезно, когда создание копии есть тяжёлая операция.
Изменяемость¶
Переменная может иметь один из трёх модификаторов изменяемости:
mut
- переменную можно будет изменять после объявленияimut
- переменную нельзя будет изменять после объявленияconstexpr
- переменная должна быть константой времени сборки
Если для переменной не указан никакой из модификаторов изменяемости, к ней будет применён модификатор imut
.
Инициализация¶
В примерах выше значения всех переменных инициализирующий при объявлении через =
.
Это не единственный способ инициализации, в зависимости от типа переменной к ней применимы различные виды инициализаторов, для переменных некоторых типов вообще можно не указывать инициализатор.
Более подробно про инициализацию читайте в соответствующей главе.
auto переменные¶
Существует возможность объявить переменную, тип которой будет выведен из типа инициализатора.
Для этого существует специальный синтаксис - объявление auto
переменной. Объявление состоит из ключевого слова auto
, опциональных модификаторов ссылочности и изменяемости, имени переменной и инициализатора после =
.
auto x = 0; // Неизменяемая auto переменная. Тип будет равен "i32".
auto mut y = 0.5f; // Изменяемая auto переменная. Тип будет равен "f32".
auto &mut y_ref= y; // Неизменяемая auto ссылка. Тип будет равен "f32".
auto &imut x_ref0= x; // Неизменяемая auto ссылка. Тип будет равен "i32".
auto & x_ref0= x; // Неизменяемая auto ссылка. Неизменяемость выбрана неявно. Тип будет равен "i32".
var [ bool, 16 ] arr= zero_init;
auto& arr_ref= arr;// Неизменяемая auto ссылка. Тип будет равен "[ bool, 16 ]".
Объявление переменных с декомпозицией¶
Существует возможность объявить несколько переменных, полученных декомпозицией непосредственного значения композитного типа.
Для декомпозиции массивов используется ключевое слово auto
, после которого идёт список переменных в []
.
Перед переменными могут быть указаны модификаторы изменяемости imut
, mut
, constexpr
.
var [ i32, 3 ] mut arr[ 1, 2, 3 ];
auto [ mut x, imut y, z ]= move(arr); // Разбираем массив на компоненты
Для кортежей синтаксис идентичен синтаксису для декомпозиции массивов.
var tup[ i32, u32 ] mut t[ 1, 2u ];
auto [ x, mut y ]= move(t); // Разбираем кортеж на компоненты
Для структур синтаксис иной - используется {}
со списком переменных, сопоставленных полям структуры.
Можно не указывать поля, значения которых не нужны.
struct S{ i32 x; f32 y; bool z; }
// ...
var S mut s{ .x= 78, .y= 13.4f, .z= false };
auto { imut a : x, mut b : y } = move(s); // Разбираем структуру на компоненты "x" и "y", пропуская "z"
Существует короткая форма указания полей - когда имя созданной переменной аналогично имени поля.
struct S{ i32 x; f32 y; }
// ...
var S mut s{ .x= 78, .y= 13.4f };
auto { mut x, y } = move(s); // Разбираем структуру на компоненты "x" и "y"
Возможна вложенность декомпозиции:
struct S{ i32 x; f32 y; bool z; }
// ...
var tup[ S, [ i32, 2 ] ] mut t[ { .x= 78, .y= 13.4f, .z= false }, [ 7, 8 ] ];
auto [ { imut a : x, mut b : y, z }, [ c, mut d ] ] = move(t);
Глобальные переменные¶
Переменные можно объявлять также вне тела функций - в глобальном пространстве, в пространствах имён, внутри структур и классов.
Но у таких переменных есть ограничение - они должны быть константами времени компиляции (constexpr
).
auto global_var = 55;
var f32 global_f0= 0.25f, global_f1 = 555.1f;
namespace NN
{
auto constexpr nn_var = global_var;
var bool imut b = global_f0 < 66.0f;
}
struct S
{
var [ i32, 42 ] zeros = zero_init;
auto constexpr zero24_plus2 = zeros[24] + 2;
}
Глобальные изменяемые переменные¶
Глобальные изменяемые переменные во многом аналогичны неизменяемым глобальным переменным.
Для них так же действует требование на constexpr
инициализатор, и они должны быть constexpr
типа.
Доступ к глобальным изменяемым переменным возможен только в unsafe
коде, включая и чтение и запись.
Это необходимо, т. к. для глобальных изменяемых переменных не работает контроль ссылок и отсутствуют механизмы синхронизации.
Программист сам должен реализовать гарантии количества ссылок и обеспечить необходимую синхронизацию доступа.
Объявляются глобальные изменяемые переменные так же, как и неимзеняемые, но с неизменяемые mut
.
auto mut global_int = 66;
var f32 mut global_float = 0.25f;
Единственное, что существенно отличает изменяемые глобальные переменные от неизменяемых, так это невозможность создания изменяемых ссылок. Они запрещены ввиду потенциальных проблем с синхронизацией доступа.
thread_local переменные¶
thread_local
переменные - это по сути те же глобальные изменяемые переменные, которые отличаются лишь тем, что каждый поток имеет свою копию такой переменной.
Ограничения для них все те же, что и для других глобальных изменяемых переменных - доступ к ним возможен только из unsafe
кода, возможны только переменные constexpr
типов.
Синтаксис объявления такой переменной особый - требуется указать ключевое слово thread_local
, после чего следует имя типа и список переменных (с инициализаторами), перечисляемых через запятую. Модификаторы ссылочности и изменяемости при этом отсутствуют.
thread_local i32 x= zero_init, y(1), z= 2;