Почему это не считается неизменным заимствованием? - PullRequest
3 голосов
/ 23 апреля 2019

Я читаю официальную Книгу ржавчины и смотрю листинг 4-8 в Разделе 4.3.

Код выглядит так:

fn first_word(s: &String) -> usize {
    let bytes = s.as_bytes();

    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return i;
        }
    }

    s.len()
}

fn main() {
    let mut s = String::from("hello world");

    let word = first_word(&s);

    s.clear();
}

Эта строка:

let word = first_word(&s);

, кажется, заимствует неизменную ссылку на s.(Здесь я предполагаю, что я не прав; я просто не знаю почему.)

В следующей строке мы изменяем s, вызывая метод clear().

Я ожидал, что компилятор сгенерирует:

cannot borrow `s` as mutable because it is also borrowed as immutable

Почему этот компилятор?

1 Ответ

5 голосов
/ 23 апреля 2019

Строка s неизменно заимствована на время разговора до first_word. Как только элемент управления возвращается к main после first_word, строка больше не считается заимствованной и может быть видоизменена, как вы заметили.


Если бы first_word вернул &String, срок действия которого вы продлили, присвоив его переменной, то вы увидите ожидаемую ошибку. Э.Г.

fn first_word(s: &String) -> &String {
    &s
}

fn main() {
    let mut s = String::from("hello world");
    let word = first_word(&s);
    s.clear();
}

не может заимствовать s как изменяемый, потому что он также заимствован как неизменный

https://rust.godbolt.org/z/cMVdVf

В этом случае добавление дополнительной области исправит это:

fn main() {
    let mut s = String::from("hello world");

    {
        let word = first_word(&s);
    }

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