Propriété (Ownership)
Orestis Malaspinas
propriété
sont ce qui rend Rust unique.propriété
est un ensemble de règles vérifiées à la compilation.garbage collector
.owner
).dropped
).
fn main()
{
let x = 5; // x est propriétaire de la mémoire contenant 5
{
let y = 6; // y est propriétaire de la mémoire contenant 5
println!("La valeur de (x,y) est: ({}, {}).", x, y);
} // y sort de la portée et est détruite avec la valeur 6
println!("La valeur de x est: {}", x);
} // x sort de la portée et sa valeur est détruite
fn main()
{
let x = [1, 2, 3, 4]; // x de type [i32; 4], sur la pile
// on ne peut pas augmenter sa taille
println!("La valeur de x est: {:?}", x);
let mut y = Vec::new(); // un vecteur dont la taille est variable
// On rajoute des éléments au vecteur avec push(elem)
y.push(1); // rust infère que le type des éléments est entier
y.push(2);
y.push(3);
y.push(4); // on lui a rajouté 4 éléments
println!("La valeur de y est: {:?}", y);
} // y sort de la portée, il est détruit et la mémoire est libérée
Flexibiliser la propriété:
move
.borrow
.Rc
et Arc
.
fn main()
{
let mut y = Vec::new(); // un vecteur dont la taille est variable
// On rajoute des éléments au vecteur avec push(elem)
y.push(1); // rust infère que le type des éléments est entier
y.push(2);
y.push(3);
y.push(4); // on lui a rajouté 4 éléments
println!("La valeur de y est: {:?}", y);
let z = y; // le vecteur (1,2,3,4) est maintenant propriété de z
// y est une variable non initialisée
println!("La valeur de z est: {:?}", z);
} // z sort de la portée, il est détruit et la mémoire est libérée
fn main()
{
let mut y = Vec::new(); // un vecteur dont la taille est variable
// On rajoute des éléments au vecteur avec push(elem)
y.push(1); // rust infère que le type des éléments est entier
y.push(2);
y.push(3);
y.push(4); // on lui a rajouté 4 éléments
println!("La valeur de y est: {:?}", y);
let z = y; // le vecteur (1,2,3,4) est maintenant propriété de z
// y est une variable non initialisée
println!("La valeur de y est: {:?}", y);
} // Ce code ne compilera pas.
move
Copy
).
fn main()
{
let y = 1;
let mut z = y; // ici si y avait été de type vecteur ont aurait fait un move
// Comme y est un i32, on en fait d'abord une copie puis
// on assigne la valeur à z
println!("Les valeurs de y et z sont : ({}, {})", y, z);
z = 2; // comme la valeur est copiée modifier z ne modifie pas y
println!("Les valeurs de y et z sont : ({}, {})", y, z);
} // Ce code compilera et s'exécutera.
move
on copie uniquement la variable, pas les données et le propriétaire des données change..clone()
.move
?Copy
:
fn take_own(_v: Vec<i32>) {
// on fait des choses
}
fn main()
{
let mut y = Vec::new(); // un vecteur dont la taille est variable
// On rajoute des éléments au vecteur avec push(elem)
y.push(1); y.push(2); y.push(3); y.push(4);
take_own(y);
println!("La valeur de y est: {:?}", y);
} // A votre avis que se passe-t-il?
fn give_own() -> Vec<i32> {
let mut y = Vec::new(); // un vecteur dont la taille est variable
// On rajoute des éléments au vecteur avec push(elem)
y.push(1); y.push(2); y.push(3); y.push(4);
v // on retourne v
}
fn main()
{
let y = give_own();
println!("La valeur de y est: {:?}", y);
} // A votre avis que se passe-t-il?
fn get_len(v: Vec<i32>) -> (Vec<i32>, usize) {
let length = v.len(); // on ajoute 2 au vecteur
(v, length) // on retourne v et sa longueur
}
fn main()
{
let mut y = Vec::new();
y.push(1); y.push(2); y.push(3); y.push(4);
let (y, length) = get_len(y);
println!("La valeur de y est: {:?} et sa longueur {}", y, length);
} // A votre avis que se passe-t-il?
move
est trop contraignant, la copie lente (et pas toujours ce qu’on veut).y
est une variable, &y
est la référence vers la variable (le pointeur vers cette variable).
fn get_len(v: &Vec<i32>) -> usize {
v.len()
}
// on sort de la prtée de la fonction,
// la propriété des données dans v est rendue.
fn main()
{
let mut y = Vec::new();
y.push(1); y.push(2); y.push(3); y.push(4);
let length = get_len(&y); // la référence vers y est passée
println!("La valeur de y est: {:?} et sa longueur {}", y, length);
}
fn get_len(v: &Vec<i32>) -> usize {
v.push(2); // on ajoute 2 à v
v.len()
}
// on sort de la prtée de la fonction,
// la propriété des données dans v est rendue.
fn main()
{
let mut y = Vec::new();
y.push(1); y.push(2); y.push(3); y.push(4);
let length = get_len(&y); // la référence vers y est passée
println!("La valeur de y est: {:?} et sa longueur {}", y, length);
}
fn get_len(v: &mut Vec<i32>) -> usize {
v.push(2); // on ajoute 2 à v
v.len()
}
// on sort de la prtée de la fonction,
// la propriété des données dans v est rendue.
fn main()
{
let mut y = Vec::new();
y.push(1); y.push(2); y.push(3); y.push(4);
let length = get_len(&mut y); // la référence vers y est passée
println!("La valeur de y est: {:?} et sa longueur {}", y, length);
}
fn dangling() -> &Vec<i32> { // la fonction retourne une référence vers un pointeur
let mut v = Vec::new();
v.push(1); v.push(2); // on a créé un vec avec 1,2 dedans.
&v; // on retourne une réf vers v
} // v sort de la portée de la fonction et est détruit:
// la mémoire est libérée.
fn main() {
let dangling_reference = dangling();
}
fn main()
{
let mut y = Vec::new();
y.push(1); y.push(2); y.push(3); y.push(4);
let y1 = &y;
let y2 = &y;
println!("La valeur de y1 et y2 sont: {:?}, {:?}.", y1, y2);
}
fn main()
{
let mut y = Vec::new();
y.push(1); y.push(2); y.push(3); y.push(4);
{
let mut y1 = &mut y;
y1.push(7);
}
println!("La valeur de y est: {:?}.", y);
}