Ownership
En Rust, une donnée sur le tas a un unique propriétaire. C’est lui qui se charge de libérer la mémoire.
Transfert d’ownership
Cette fonction crée un vecteur avec 5 et 12 dedans. C’est v qui est le propriétaire. En faisant, v2 = v, on met les données dans v2 qui devient le propriétaire des données. v ne possède plus rien. C’est de la move semantics.
fn main() {
let v = vec![5, 12];
let v2 = v;
println!("{}", v[0]); // non
}
Pareil, si on appelle une fonction sur v, c’est l’argument dans f qui est le propriétaire.
#![allow(unused)]
fn main() {
fn f(argv: Vec<i32>) {
...
}
}
fn main() {
let v = vec![5, 12];
f(v);
println!("{}", v[0]); // non
}
Une solution pourrait être que la fonction renvoie v pour que v redevienne propriétaire des données :
fn main() {
let v = vec![5, 12];
v = f(v);
println!("{}", v[0]); // non
}
Mais ça peut être lourdingue, surtout si une fonction a plusieurs paramètres, ou si on veut renvoyer une autre valeur.
Références et emprunt
#![allow(unused)]
fn main() {
fn f(argv: &Vec<i32>) {
...
}
}
Le & permet d’emprunter des données, les utiliser, mais sans en être propriétaire. La fonction f ici ne va pas détruire le vecteur. C’est une référence. Penser une référence Rust comme un pointeur C (et pas comme une référence C++), comme une adresse mémoire.
Contrairement à C, le pointeur nul n’existe pas dans le langage Rust. (il existe dans son implémentation)
Déréférencement
Comme en C, *argv signifie les données à l’adresse argv.
fn f(argv: &Vec<i32>) {
println!("{}", (*argv)[1]);
}
fn main() {
let v = vec![5, 12];
f(&v);
println!("{}", v[0]);
}
Mais en fait, il y a du déférencement automatique. Donc l’étoile * peut être omise :
fn f(argv: &Vec<i32>) {
println!("{}", argv[1]);
}
fn main() {
let v = vec![5, 12];
f(&v);
println!("{}", v[0]);
}
Règles d’emprunt
- Une référence ne peut pas vivre plus longtemps que la variable qu’elle référence. Ce code est faux :
#![allow(unused)]
fn main() {
let reference: &i32;
{
let x = 5;
reference = &x;
}
println!("{}", reference);
}
- Autant de références immutables que l’on veut
- Au plus une référence mutable sur une variable mutable
- Impossible d’avoir une référence mutable et une autre immutable sur une même variable