Blog · 2026-06-19Blog · 2026-06-19

L'ownership en Rust : le move expliqué Ownership in Rust: the move explained

Pas de garbage collector, pas de free() manuel. Comment Rust libère la mémoire pile au bon moment grâce à une seule idée : chaque valeur a un propriétaire unique.No garbage collector, no manual free(). How Rust frees memory at exactly the right moment with one idea: every value has a single owner.

RustOwnershipMoveMémoire

Les langages se rangent en deux camps pour gérer la mémoire : un ramasse-miettes qui passe derrière vous (Java, Go, Python), ou un free() manuel que vous risquez d’oublier (C, C++). Rust refuse les deux. Sa réponse tient en une phrase : chaque valeur a un propriétaire unique, et quand le propriétaire disparaît, la valeur est libérée. C’est l’ownership.

Le move : transférer, pas copier

Affecter une valeur ne la duplique pas — ça transfère sa possession :

let a = String::from("Ada");
let b = a;            // la possession de la String passe de `a` à `b`
println!("{a}");      // ❌ erreur : `a` ne possède plus rien — value moved

Pour beaucoup de débutants c’est un choc : let b = a; invalide a. C’est un move. Rust interdit d’utiliser a ensuite, parce que sinon a et b pointeraient vers la même mémoire — et tous deux tenteraient de la libérer en fin de portée. C’est le bug du double free, rendu tout simplement impossible.

Pourquoi pas une copie ?

Parce qu’une String possède un tampon sur le tas. Copier a dans b demanderait soit de partager le tampon (et revoilà le double free), soit de le cloner — une allocation que vous n’avez pas demandée. Rust choisit l’option la plus honnête : il déplace, gratuitement, et vous laisse cloner explicitement si vous le voulez vraiment :

let a = String::from("Ada");
let b = a.clone();   // copie profonde, explicite : deux tampons distincts
println!("{a} et {b}");   // ✅ `a` est toujours valide

Les types simples posés sur la pile (i32, bool, char…) implémentent Copy : eux sont copiés bit à bit, sans move, parce que ça ne coûte rien et qu’il n’y a aucun tampon à libérer.

Le résultat : Drop au bon moment

Quand b sort de portée, Rust appelle drop et libère le tampon — exactement une fois, exactement là où il faut. Pas de GC qui se réveille à un moment imprévisible, pas de free() oublié. La gestion mémoire devient une propriété du type, vérifiée à la compilation.

C’est la fondation de tout Rust : maîtrisez le move, et le reste (emprunts, lifetimes, concurrence) n’est que la suite logique de cette même idée.

Languages fall into two camps for memory management: a garbage collector that cleans up behind you (Java, Go, Python), or a manual free() you might forget (C, C++). Rust rejects both. Its answer fits in one sentence: every value has a single owner, and when the owner goes away, the value is freed. That’s ownership.

The move: transfer, don’t copy

Assigning a value doesn’t duplicate it — it transfers ownership:

let a = String::from("Ada");
let b = a;            // ownership of the String moves from `a` to `b`
println!("{a}");      // ❌ error: `a` owns nothing anymore — value moved

For many beginners it’s a shock: let b = a; invalidates a. That’s a move. Rust forbids using a afterwards, because otherwise a and b would point to the same memory — and both would try to free it when they go out of scope. That’s the double free bug, simply made impossible.

Why not a copy?

Because a String owns a heap buffer. Copying a into b would mean either sharing the buffer (double free again) or cloning it — an allocation you never asked for. Rust picks the honest option: it moves, for free, and lets you clone explicitly when you truly want to:

let a = String::from("Ada");
let b = a.clone();   // explicit deep copy: two separate buffers
println!("{a} and {b}");  // ✅ `a` is still valid

Simple stack types (i32, bool, char…) implement Copy: they’re copied bit for bit, no move, because it costs nothing and there’s no buffer to free.

The payoff: Drop at the right moment

When b goes out of scope, Rust calls drop and frees the buffer — exactly once, exactly where it should. No GC waking up at an unpredictable time, no forgotten free(). Memory management becomes a property of the type, checked at compile time.

This is the foundation of all of Rust: master the move, and the rest (borrows, lifetimes, concurrency) is just the logical continuation of the same idea.

Tous les articlesAll articles