#rust
#Ржавчина
Вопрос:
У меня есть функция, которая принимает изменяемую ссылку на строку и добавляет некоторый текст.
fn append_str(s: amp;mut String) {
s.push_str(" hi");
}
Предположим, у меня есть строка.
let mut s: String = "hi".to_string();
Если я создаю изменяемую ссылку на s
и передаю ее append_str
, она компилируется без проблем.
let mut ss = amp;mut s;
append_str(amp;mut ss);
Однако, если я явно определяю ss
с amp;mut String
помощью, он не компилируется.
let ss: amp;mut String = amp;mut s;
append_str(amp;mut ss);
это показывает следующую ошибку компилятора.
|
80 | let ss: amp;mut String = amp;mut s;
| -- help: consider changing this to be mutable: `mut ss`
81 | append_str(amp;mut ss);
| ^^^^^^^ cannot borrow as mutable
Забавно то, что если я разыменую ее, то это сработает.
let ss: amp;mut String = amp;mut s;
append_str(amp;mut *ss); // OK
По какой причине мы должны явно разыменовывать в этом случае?
Еще один вопрос: почему мы должны указывать mut
на ссылку, если мы хотим передать ее функции?
let ss = amp;mut s;
append_str(amp;mut ss); // ERROR
Ответ №1:
ss
это уже ссылка, поэтому amp;mut ss
дает вам (изменяемую) ссылку на (изменяемую) ссылку; если у вас есть ss
, вы должны вызвать append_str
с ней напрямую: append_str(ss)
.
Это происходит только тогда, когда вы неправильно принимаете изменяемую ссылку на ss
, вам нужно объявить ее как mut ss
. Обычный вариант использования для чего-то подобного — передать это функции, которая фактически принимает x: amp;mut amp;mut String
и использует что-то вроде *x = amp;mut some_other_string
, чтобы сделать ss
ссылку на другую ссылку на строку. В вашем случае «исправленный» код с mut
компилируется, потому что компилятор автоматически разыменовывает двойную ссылку для вас.