#rust
#Ржавчина #константы #неизменность
Вопрос:
Я узнал, что если переменная явно не объявлена изменяемой с помощью mut
, она становится неизменяемой (ее нельзя изменить после объявления). Тогда почему у нас есть const
ключевое слово в Rust? Разве они не одинаковые? Если нет, то чем они отличаются?
Ответ №1:
const
в Rust сокращение от constant и связано с оценкой во время компиляции. Он появляется:
- при объявлении констант:
const FOO: usize = 3;
- при объявлении оцениваемых функций во время компиляции:
const fn foo() -> amp;'static str
Эти типы значений могут использоваться в качестве общих параметров : [u8; FOO]
. На данный момент это ограничено размером массива, но есть разговоры, планы и надежда расширить его в будущем.
В отличие от этого, let
привязка относится к вычисляемому значению во время выполнения.
Обратите внимание, что, несмотря mut
на то, что они используются, поскольку концепция изменчивости хорошо известна, Rust на самом деле лежит здесь. amp;T
и amp;mut T
речь идет об псевдонимах, а не о изменчивости:
amp;T
: общая ссылкаamp;mut T
: уникальная ссылка
Наиболее примечательно, что некоторые типы обладают внутренней изменчивостью и могут быть изменены с помощью amp;T
(общих ссылок): Cell
, RefCell
, Mutex
, и т.д.
Примечание: существует альтернативное использование mut
и const
с необработанными указателями ( *mut T
и *const T
), которое здесь не обсуждается.
Комментарии:
1. doc.rust-lang.org/std/primitive.pointer.html — вот использование необработанного указателя, он также упоминается здесь .. doc.rust-lang.org/1.30.0/book/2018-edition /… — но за этим не так-то легко уследить.
Ответ №2:
const
не для переменных; это для постоянных значений, которые могут нигде не храниться; они фактически являются псевдонимом для буквального значения.
Не mut
let
объявляет фактическую переменную, которая создается во время выполнения, может быть перемещена (и больше недоступна) и даже имеет внутреннюю изменчивость (например, если она содержит Cell
элементы) в некоторых случаях.
Ответ №3:
A const
представляет не ячейку памяти, а значение. const
значения напрямую встроены в местоположение использования. Любые временные объекты, которые создаются во время вычисления выражения, доступны только компилятору во время компиляции. Может быть ограничено глобально. Невозможно ссылаться на элементы среды выполнения. Должно быть аннотировано по типу.
Пусть значения представляют ячейку памяти. Неизменность для let
привязки — это принудительная функция компилятора, которую можно изменить с mut
помощью модификатора. Это конструкция времени выполнения. Всегда локально скопировано. Их типы могут быть определены компилятором.
Для полноты картины a static
также представляет ячейку памяти, например let, но любые ссылки на один и тот же static фактически являются ссылкой на одну и ту же ячейку памяти. Статика — это, ну, статика. Они компилируются в исполняемый файл и доступны в течение всего срока службы запущенной программы. Может быть ограничено глобально. Может ссылаться на другую статику. Должно быть аннотировано по типу.
Ответ №4:
Константы не могут быть затенены:
let x = 10u32;
const Y:u32 = 20u32;
let x = 11u32;
//error: duplicate definition of value `Y` [E0428]
//const Y:u32 = 21u32;
println!("x={} Y={}",x,Y); //x=11 Y=20
Ответ №5:
Кроме того, мы не можем создавать глобальные элементы с помощью let , но это возможно с помощью const . Вот пример.
const LENGTH:usize = 4;
fn main() {
let arr:[i32; LENGTH] = [10,20,30,40];
for i in 0..LENGTH{
println!("{}", arr[i])
}
}
для получения дополнительной информации об использовании const , static и let:
const
и static
История немного длиннее.
Ответ №6:
const
предназначен для констант времени компиляции со всеми вытекающими последствиями. Например, вы можете создать массив фиксированного размера, размер которого равен a const
, но вы не можете сделать это с let
помощью привязки. Конечно, это также означает, что вы можете поместить гораздо, гораздо больше вещей в let
привязку, чем в const
.
Ответ №7:
Концептуально const
элементы заменяются перед синтаксическим анализом, подобно тому, что делает C-макрос. Это позволяет использовать его в обстоятельствах, когда обычные переменные не разрешены.
const TEN: u32 = 10;
let ten = 10;
// OK
match x {
TEN => do_a(),
_ => do_b(),
}
// Nah...
match x {
ten => do_a(),
_ => do_b(),
}
// ...use this instead
match x {
y if x == ten => do_a(),,
_ => do_b(),
}