ПрограммированиеBackend разработчик

Объясните, что такое константы и статические переменные в Rust, каковы их отличия и в каких случаях предпочтительнее использовать каждую из них?

Проходите собеседования с ИИ помощником Hintsage

Ответ

В 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, забыв о том, что строковые литералы с ссылками используют область памяти программы, а 일부 объявлений на самом деле требовали только подстановки значения: это увеличило размер бинарника и усложнило управление памятью. Итог — рост времени запуска и утечки при динамической подгрузке библиотек.