Немного о static

от автора


Чуть-чуть о статье

Теперь попробуем создать что-то вроде «глобальной переменной» с помощью ключевого слова static.

«Они похожи на постоянные, но статические значения не встраиваются в место их использования. Это значит, что каждое значение существует в единственном экземпляре, и у него есть определённый адрес».

Объявим её:

static N = 8;  fn main() { 		println!("N = {}",N); } 

Компилируем. Выход:

error: expected ‘:’, found ‘=’
static N = 8;
~~~~~~~^

Как видно, нам и в этом случае необходимо указывать тип. Исправляем:

static N: i32 = 8; 

И у нас всё в порядке. Выход:

N = 8

Пробуем так:

static N: i32 = 4; static N: i32 = 5;  fn main() { 	println!("N = {}",N); } 

Выход:

error: duplicate definition of value `N` [E0428]

Так же как и с константами. Ясно. Продолжаем делать всё, что делали с константами:

static N: i32 = 4; fn main() {     println!("N = {}",N);     static N: i32 = 8;     println!("N = {}",N); } 

Выход:

warning: static item is never used: `N`, #[warn(dead_code)] on by default
static N: i32 = 4;
^~~~~~~~~~~~~~~~~

Так же как и с константами. Пробуем дальше:

static N: i32 = 4; fn main() {     println!("N = {}",N);     static N: i32 = 8;     println!("N = {}\n",N);     other(); }  fn other() {     println!("N = {}",N); }  

Выход:

N = 8
N = 8

N = 4

Далее:

static N: i32 = 4; fn main() {     println!("N = {}",N);     static M: i32 = 8;     println!("M = {}\n",M);     other(); }   fn other() {     println!("N = {}",N); } 

То выход будет таким:

N = 4
M = 8

N = 4

И ещё один эксперимент:

fn main() {     println!("N = {}",N);     static N: i32 = 8;     static N: i32 = 9;     println!("N = {}\n",N); } 

Выход:

error: duplicate definition of value `N` [E0428]
static N: i32 = 9;
^~~~~~~~~~~~~~~~~

Следующий:

fn main() {     println!("N = {}",N);     static N: i32 = 8; 	{     	static N: i32 = 9; 	}        println!("N = {}\n",N); }  

Выход:

N = 8
N = 8

Можно и так:

fn main() {     println!("N = {}",N);     static N: i32 = 8; 	{     	println!("N = {}\n",N); 	}        println!("N = {}\n",N); } 

Выход:

N = 8
N = 8

N = 8

А если так:

fn main() {     println!("N = {}",N); 	{     	static N: i32 = 8;     	println!("N = {}\n",N); 	}        println!("N = {}\n",N); } 

Выход:

error: unresolved name `N` [E0425]
println!(«N = {}»,N);
~~~~~~~~~~~~^

Ещё:

static N: i32 = 3;  fn main() {     println!("N = {}",N); 	{     	static N: i32 = 8;     	println!("N = {}\n",N); 	}        println!("N = {}\n",N); } 

Выход:

N = 3
N = 8

N = 3

Короче, здесь всё было как с константами. Попробуем сделать переменную изменяемой:

fn main() { 		println!("{} = n",N); 		static mut N: i32 = 8; } 

Выход:

error: use of mutable static requires unsafe function or block [E0133]
println!("{} = N",N);

Говорит, типо, это слишком небезопасно.

«По скольку N изменяемо, один поток может изменить его во время того, как другой читает его значение. Это ситуация «гонки» по данным, и она считается небезопасным поведением в Rust. Поэтому и чтение, и изменение статическ ого изменяемого зна чения( static mut ) является небезопасным (unsafe), и обе эти операции должны выполняться в небезопасных блоках ( unsafe block)».

Поэтому делаем так:

fn main() { 		unsafe { 			println!("{} = N",N); 		} 		static mut N: i32 = 8; } 

Выход:

8 = N

Можем сделать так:

fn main() { 		unsafe { 			println!("{} = n",N); 			static mut N: i32 = 8; 		} 		println!("{} = n",N); } 

Но тогда N не будет видно для второго println!(…). Нам вернут ошибку:

error: unresolved name ‘N’ [E0425]
println!("{} = N",N);

Если сделать её глобальной, то работает:

static mut N: i32 = 8; fn main() { 		unsafe { 			println!("{} = n",N); 		} 		 } 

Выход:

8 = N

Теперь ссылки.

«Каждое значение существует в единственном экземпляре, и у него есть определённый адрес. Статические зна чения живут в течение всего времени работы программы, и любая ссылка
на постоянную имеет статическ ое время жизни ( static lifetime)».

static N: i32 = 8 fn main() {     let x = &N;     println!("{} = N",N);     println!("{} = N",*x);     println!("{:p} -> N",&N);     println!("{:p} -> N",x); } 

Выход:

N = 8
N = 8
0x8010b884 -> N
0x8010b884 -> N

Ну, там ещё есть такое:

«Более того, любой тип, хранимый в статическ ой переменной, должен быть ограничен
Sync и не может иметь реализации Drop ».

Но я не знаю что это значит и буду очень рад, если кто-то зкажет, что это значит…

Литература:

The Rust Reference (английский)
The Rust Programming Language (английский)
The Rust Programming Language (русский)

ссылка на оригинал статьи https://habrahabr.ru/post/275791/


Комментарии

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

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