В Rust существуют два основных способа для хранения неизменяемых данных на протяжении исполнения программы: const и static.
Константа (const) — это неизменяемое значение, вычисляющееся во время компиляции. Она обязана быть всегда явно типизирована и инициализирована константным выражением (которое может быть вычислено на этапе компиляции). Константы не имеют фиксированного адреса в памяти и «вставляются» компилятором в места использования.
const MAX_ATTEMPTS: u32 = 5;
Статическая переменная (static) хранит значение в определённой области памяти на всём протяжении выполнения программы. Её адрес фиксирован, и она может быть изменяемой (с использованием static mut), но обращаться к ней требуется с особыми предосторожностями из-за возможных гонок данных в многопоточных сценариях.
static APP_NAME: &str = "MyApp"; static mut COUNTER: u32 = 0;
const, когда значение должно быть всегда известно в compile-time и не нужно мировое хранилище.static, если требуется единственное место хранения в памяти, к которому все модули получают доступ, или если значение не может быть вычислено на этапе компиляции.В чём разница между
constиstaticв Rust? Может ли статическая переменная ссылаться на не-константу?
Ответ: Основное отличие — область хранения (lifetime): const не гарантирует существования света в памяти (это подстановка значения), а static — это объект, живущий на всём протяжении программы с фиксированным адресом.
Статической переменной можно присвоить только значение, известное на этапе компиляции:
let a = 42; // static INVALID: i32 = a; // Ошибка! Только константы допустимы.
История
В проекте backend-сервиса для распределения нагрузки один из разработчиков использовал static mut для общего счётчика обращений из разных потоков, не используя синхронизацию. Это привело к гонкам данных и непредсказуемым результатам — часть обращений просто терялась. Решение — использовать атомарные типы из std::sync::atomic, либо Mutex.
История
Молодой разработчик решил вынести строку приветствия пользователя в константу с помощью const, но попытался связать её с результатом функции, вычисляемой во время инициализации. Компилятор выдал ошибку, потому что значение должно быть определено на этапе компиляции. Причина — константа должна быть пригодна к вычислению в compile-time, тогда как функция возвращает значение во время выполнения.
История
В старом проекте заменили все глобальные значения на static, забыв о том, что строковые литералы с ссылками используют область памяти программы, а 일부 объявлений на самом деле требовали только подстановки значения: это увеличило размер бинарника и усложнило управление памятью. Итог — рост времени запуска и утечки при динамической подгрузке библиотек.