В чем разница между неизменяемыми и постоянными переменными в Rust?

#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(),
}