В Rust, как ссылка может быть указателем на указатель на указатель?
сегодняшняя загадка ржавчины из раздела 4.9 языка программирования ржавчины, первое издание. Пример ссылок и заимствований имеет следующий пример:
fn main() {
fn sum_vec(v: &Vec<i32>) -> i32 {
return v.iter().fold(0, |a, &b| a + b);
}
fn foo(v1: &Vec<i32>) -> i32 {
sum_vec(v1);
}
let v1 = vec![1, 2, 3];
let answer = foo(&v1);
println!("{}", answer);
}
это кажется разумным. Он печатает "6", что вы ожидали бы, если бы
v
of sum_vec
является ссылкой на C++; это просто имя для памяти
местоположение, вектор v1
мы определили в main()
.
затем Я заменил тело sum_vec
С этого:
fn sum_vec(v: &Vec<i32>) -> i32 {
return (*v).iter().fold(0, |a, &b| a + b);
}
он составлен и работал, как и ожидалось. Ладно, это не совсем ... безумие. Компилятор пытается сделать мою жизнь проще, я понимаю. Запутанный, что-то, что я должен запомнить как конкретный ТИК языка, но не совсем сумасшедший. Тогда я попробовал:--11-->
fn sum_vec(v: &Vec<i32>) -> i32 {
return (**v).iter().fold(0, |a, &b| a + b);
}
он все еще работал! Какого черта?
fn sum_vec(v: &Vec<i32>) -> i32 {
return (***v).iter().fold(0, |a, &b| a + b);
}
type [i32] cannot be dereferenced
. Слава богу, хоть что-то разумное. Но я ожидал, что почти две итерации раньше!
ссылки в Rust не являются C++ "имена для другого места в памяти", но что?--23-- > are они? Они также не являются указателями, и правила о них кажутся либо эзотерическими, либо очень специальными. Что происходит так, что ссылка, указатель и указатель на указатель работают одинаково хорошо здесь?
1 ответов
правила не ad-hoc не совсем эзотерика. Проверьте тип v
и это различные разыменовывает:
fn sum_vec(v: &Vec<i32>) {
let () = v;
}
вы получите:
-
v
->&std::vec::Vec<i32>
-
*v
->std::vec::Vec<i32>
-
**v
->[i32]
первое разыменование вы уже поняли. Второе разыменование происходит благодаря Deref
черта. Vec<T>
разыменовывает к [T]
.
при выполнении поиска метода, есть прямой набор правил:
- если тип имеет метод, используйте его и закройте поиск.
- если ссылка на тип имеет метод, используйте его и закройте поиск.
- если тип может быть разыменован, сделайте это, затем вернитесь к шагу 1.
- иначе поиск завершается неудачно.
ссылки в Rust не являются именами C++ для другое место в памяти,"
они абсолютно являются именами для места в памяти. Фактически, они компилируются до того же указателя C / C++, который вы знаете.