Ключевое слово static
Статический элемент — это значение, которое действительно в течение всего времени выполнения вашей программы (время жизни 'static).
На первый взгляд, статические элементы кажутся очень похожими на константы: оба содержат значение, оба требуют аннотаций типов и оба могут быть инициализированы только константными функциями и значениями. Однако статические элементы заметно отличаются тем, что представляют собой расположение в памяти. Это означает, что вы можете иметь ссылки на статические элементы и потенциально даже изменять их, делая их по сути глобальными переменными.
Статические элементы не вызывают drop в конце программы.
Существует два типа статических элементов: объявленные с ключевым словом mut и без него.
Статические элементы не могут быть перемещены: ⓘ
#![allow(unused)] fn main() { static VEC: Vec<u32> = vec![]; fn move_vec(v: Vec<u32>) -> Vec<u32> { v } // Эта строка вызывает ошибку move_vec(VEC); }
Простые статические элементы (без mut)
Доступ к неизменяемым статическим элементам считается безопасным, но применяются некоторые ограничения. Наиболее notably, тип статического значения должен реализовывать трейт Sync, что исключает контейнеры с внутренней изменчивостью, такие как RefCell. См. Справочник для получения более подробной информации.
#![allow(unused)] fn main() { static FOO: [i32; 5] = [1, 2, 3, 4, 5]; let r1 = &FOO as *const _; let r2 = &FOO as *const _; // С строго доступным только для чтения статиком ссылки будут иметь тот же адрес assert_eq!(r1, r2); // Статический элемент может использоваться так же, как переменная, во многих случаях println!("{FOO:?}"); }
Изменяемые статические элементы (с mut)
Если статический элемент объявлен с ключевым словом mut, то программе разрешено его изменять. Однако доступ к изменяемым статикам может вызвать неопределённое поведение различными способами, например, из-за гонки данных в многопоточном контексте. Как таковой, весь доступ к изменяемым статикам требует блока unsafe.
Когда это возможно, часто лучше использовать неизменяемый статик с типом внутренней изменчивости, таким как Mutex, OnceLock или атомарный тип.
Несмотря на их небезопасность, изменяемые статики необходимы во многих контекстах: они могут использоваться для представления глобального состояния, разделяемого всей программой, или в блоках extern для привязки к переменным из библиотек C.
В блоке extern:
#![allow(unused)] fn main() { unsafe extern "C" { static mut ERROR_MESSAGE: *mut std::os::raw::c_char; } }
На изменяемые статики, как и на простые статики, распространяются некоторые ограничения. См. Справочник для получения более подробной информации.