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.

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...

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