Sou novo no Rust e acho que alguns comportamentos do Rust não são intuitivos
digamos que temos o código abaixo:
struct User {
name: String,
email:String
}
fn main() {
let some_vec = vec![String::from("value1"),String::from("value2")];
let _v = some_vec[0];
let user = User {
name:String::from("name"),
email:String::from("email")
};
let user_ref = &user;
let _name = user_ref.name;
let _email = user.email;
}
e o compilador reclama que:
error[E0507]: cannot move out of index of `Vec<String>`
--> src/main.rs:19:14
|
19 | let _v = some_vec[0];
| ^^^^^^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait
|
help: consider borrowing here
|
19 | let _v = &some_vec[0];
| +
error[E0507]: cannot move out of `user_ref.name` which is behind a shared reference
--> src/main.rs:28:17
|
28 | let _name = user_ref.name;
| ^^^^^^^^^^^^^ move occurs because `user_ref.name` has type `String`, which does not implement the `Copy` trait
|
help: consider borrowing here
|
28 | let _name = &user_ref.name;
| +
- Eu penso
Vec
eStruct
sou semelhante em agrupar valores. então pensei que se não podemos mover String de vec via índice, também não podemos mover String do campo struct. mas não há erro emlet _email = user.email;
- Eu sei que não podemos sair de uma referência, assim:
let v = vec![1, 2, 3];
let v_ref: &Vec<i32> = &v;
let v2 = *v_ref;// move occurs because `*v_ref` has type `Vec<i32>`, which does not implement the `Copy` trait
então o código let _name = user_ref.name
é, na verdade, let _name = (*user_ref).name
após a desreferência do compilador automaticamente? É uma maneira semelhante de sair de uma referência como o código acima?
Não são, porque uma "estrutura" é "transparente" para o compilador, já que o compilador é capaz de detectar diferentes campos de uma estrutura, o que não é o caso da indexação
vec
, que é uma operação opaca. É por isso que você pode emprestar exclusivamente diferentes campos de uma estrutura, mas não diferentes índices de um vec.Isso ocorre porque ele está realizando um movimento parcial para fora da estrutura, depois você não pode passar por
user
si mesmo como uma unidade (por exemplo, como parâmetro para uma função):nem acesso
user.email
:você só pode acessar os outros campos da estrutura.
Isso é o que significa desreferência automática , sim. Ele desreferencia automaticamente.