Как распечатать значение после изменяемого заимствования? - PullRequest
0 голосов
/ 24 сентября 2019

Я строю строку, затем заимствую ее, чтобы внести некоторые изменения.Затем я хочу посмотреть, как изменяется строка, но не могу распечатать значение:

let mut s1 = String::from("hello");
let s2 = &mut s1;
s2.truncate(2);
print!("{}", s1);
println!("{}", s2);
error[E0502]: cannot borrow `s1` as immutable because it is also borrowed as mutable
 --> src/lib.rs:5:18
  |
3 |     let s2 = &mut s1;
  |              ------- mutable borrow occurs here
4 |     s2.truncate(2);
5 |     print!("{}", s1);
  |                  ^^ immutable borrow occurs here
6 |     println!("{}", s2);
  |                    -- mutable borrow later used here

Я думал, что заимствование в Rust похоже на C ++, поэтому при изменении s1 s2 будет изменено соответственно.

Ответы [ 2 ]

1 голос
/ 24 сентября 2019

Ссылки Rust не работают, как в других языках, таких как C / C ++ / Java.Компилятор Rust обеспечивает безопасность памяти во время компиляции и делает это с помощью «средства проверки заимствований».Средство проверки заимствования придерживается набора правил, и опубликованный вами код нарушает одно из них.

Вот прямая цитата из книги Rust, в которой указан этот точный ситуация:

  • В любой момент времени вы можете иметь одну изменяемую ссылку или любое количество неизменяемых ссылок.

Сначала вы создаете изменяемуюпеременная s1, и заимствовать ее как неизменную через s2.Это нормально, если вы не используете оба из них одновременно .Проблема не возникает здесь, потому что вы еще ничего не сделали со ссылками.Проблема возникает, когда вы заставляете эти две ссылки быть активными одновременно.Это происходит, когда вы получаете доступ к s1 до того, как s2 выйдет из области видимости (это будет после последнего использования).Взгляните на это:

  let mut s1 = String::from("hello"); // -- Start of s1 scope --
  let s2 = &mut s1;                       // -- Start of s2 scope --
  s2.truncate(2);                         // s1 may not be used here as
                                          // that breaks the rules
  print!("{}", s1);                   // -- End of s1 scope --
  println!("{}", s2);                     // -- End of s2 scope --

Как видите, из-за структуры вашего кода области действия s1 и s2 должны быть активными одновременно.Если бы вам пришлось поменять местами последние две строки кода, изменив код следующим образом:

  let mut s1 = String::from("hello"); // -- Start of s1 scope --
  let s2 = &mut s1;                       // -- Start of s2 scope --
  s2.truncate(2);                         // s1 may not be used here as
                                          // that breaks the rules
  println!("{}", s2);                     // -- End of s2 scope --
  print!("{}", s1);                   // -- End of s1 scope --

Тогда ваш код скомпилировался бы и работал как ожидалось.Причина в том, что, хотя область действия s2 активна, вы вообще не используете s1.Другими словами, эти вещи происходят в каждой строке приведенного выше кода:

  1. s1 вновь владеет созданным String
  2. s2 с возможностью заимствования String
  3. s2 используется для усечения String
  4. s2 используется для печати String.Поскольку это последнее использование s2, после этой строки владение String возвращается к s1.
  5. s1 используется для печати String.

Надеюсь, это прояснит ситуацию для вас.

Я бы посоветовал вам уделить время тому, чтобы взглянуть на главу книги Rust "Понимание владения" здесь .Мой совет - прочитать всю книгу, начиная с самого начала.Это даст вам очень хорошее понимание Rust как языка и его экосистемы.

0 голосов
/ 25 сентября 2019

(Я тот, кто задал вопрос.) Мне нравится ответ @mrzenioszeniou, и я впечатлен неизменяемая ссылка и изменяемая ссылка не могут быть активными одновременно .Я также попробовал этот код:

   let mut s1 = String::from("hello");
    {
        let s2 = &mut s1;
        s2.truncate(2);
    } //--End of s2 scope
   println!("{}", s1);

Здесь я добавляю s2 как &mut s1 в новую дочернюю область, когда область заканчивается, это не повлияет на неизменный заем s1.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...