Как Rust реализует индексацию массива?

Я изучаю системы подструктурных типов, и Rust — хороший тому пример.

В Rust массив изменяем, и к нему можно обращаться много раз, а не только один раз. В чем разница между «чтением значения», «чтением ссылки» и «чтением изменяемой ссылки»? Я написал программу, как показано ниже, но получил несколько ошибок.

fn main() {
    let xs: [i32; 5] = [1, 2, 3, 4, 5];
    println!("first element of the array: {}", xs[1]);
    println!("first element of the array: {}", &xs[1]);
    println!("first element of the array: {}", &mut xs[1]);
}

Вот сообщение об ошибке:

error[E0596]: cannot borrow immutable indexed content `xs[..]` as mutable
 --> src/main.rs:5:53
  |
2 |     let xs: [i32; 5] = [1, 2, 3, 4, 5];
  |         -- consider changing this to `mut xs`
...
5 |     println!("first element of the array: {}", &mut xs[1]);
  |                                                     ^^^^^ cannot mutably borrow immutable field

person Coding_Rabbit    schedule 16.01.2018    source источник
comment
Я не думаю, что Array по умолчанию изменяемы; отсюда и ваша ошибка.   -  person erip    schedule 16.01.2018
comment
Если вы знакомы с C++... value reads сопоставляется с семантикой return-by-value, reference reads сопоставляется с корректной константой семантикой return-by-reference, а mutable reference reads в большинстве случаев является плохой идеей и просто относится к семантике return-by-reference.   -  person erip    schedule 16.01.2018


Ответы (1)


xs не изменяется; чтобы сделать его изменяемым, его привязка должна содержать ключевое слово mut:

let mut xs: [i32; 5] = [1, 2, 3, 4, 5];

Когда вы добавите его, ваш код будет работать так, как ожидалось. Я рекомендую соответствующий раздел в The Rust Book.

Индексирование в Rust — это операция, предоставляемая Index и IndexMut и, как указано в документации, синтаксический сахар для *container.index(index) и *container.index_mut(index), что означает, что он обеспечивает прямой доступ (а не только ссылку) к индексируемому элементу. Различия между тремя перечисленными вами операциями лучше видны при assert_eq сравнениях:

fn main() {
    let mut xs: [i32; 5] = [1, 2, 3, 4, 5];

    assert_eq!(xs[1], 2); // directly access the element at index 1
    assert_eq!(&xs[1], &2); // obtain a reference to the element at index 1
    assert_eq!(&mut xs[1], &mut 2); // obtain a mutable reference to the element at index 1

    let mut ys: [String; 2] = [String::from("abc"), String::from("def")];

    assert_eq!(ys[1], String::from("def"));
    assert_eq!(&ys[1], &"def");
    assert_eq!(&mut ys[1], &mut "def");
}
person ljedrz    schedule 16.01.2018
comment
На самом деле вы не ответили на вопрос (вопросы) OP: Как Rust реализует функцию чтения массива? и В чем разница между чтением значения, чтением ссылки и чтением изменяемой ссылки? - person Shepmaster; 16.01.2018
comment
Я изменил код и превратил массив xs в изменяемый, но я до сих пор не знаю, в чем разница между этими тремя способами чтения массива. Не могли бы вы дать мне какое-нибудь объяснение? - person Coding_Rabbit; 16.01.2018
comment
@Coding_Rabbit Я немного расширил ответ; Думаю, теперь стало понятнее. - person ljedrz; 16.01.2018