Considérons l'historique de la question :
En Rust, le concept de gestion de la mémoire et de propriété nécessite une définition claire de la manière dont les objets sont déplacés et copiés. Aux débuts du langage, il était important de distinguer la simple copie de bytes (sans allocations et logique) et le clonage profond (par exemple, une copie de chaîne, de vecteur). Pour cela, deux traits ont été introduits — Copy et Clone.
Le problème est que tous les types de données ne sont pas copiés de manière aussi économique. Pour certaines structures, la copie n'est qu'une copie de bits (par exemple, des entiers ou des tuples de types Copy), tandis que pour d'autres (par exemple, String, Vec), un travail supplémentaire d'allocation de mémoire est requis. La séparation de Copy et Clone permet à Rust de produire une erreur de compilation si une tentative de copie invalide est faite.
Solution :
Copy sont automatiquement copiés lors de la transmission, de l'assignation et du passage à des fonctions. Les objets de ces types restent valides après la copie.Clone est implémenté, ce qui implique un appel explicite à la méthode .clone(), souvent avec une allocation de ressources supplémentaire.Exemple de code :
#[derive(Debug, Copy, Clone)] struct Point { x: i32, y: i32, } fn main() { let p1 = Point { x: 1, y: 2 }; let p2 = p1; // p1 ne devient pas "invalide" println!("{:?} {:?}", p1, p2); }
Caractéristiques clés :
Copy - copie par bits automatique, ne nécessite pas d'appel manuel et n'affecte pas la propriété.Clone - copie profonde explicite, adapté pour des structures avec des données sur le tas.Les types avec des données allouées sur le tas peuvent-ils avoir la dérivation Copy ?
Non, les types contenant des données sur le tas (par exemple, String, Vec) ne peuvent pas automatiquement implémenter Copy, car cela entraînerait une double libération de mémoire.
Si un type implémente Copy, peut-on également l'implémenter Clone manuellement avec une autre logique ?
Oui, Clone peut être implémenté manuellement et la logique peut différer, cependant, il est recommandé que Copy et Clone soient cohérents : Copy appelle simplement Clone sans allocations.
#[derive(Copy)] struct X; impl Clone for X { fn clone(&self) -> X { *self } }
Si une structure contient uniquement des champs Copy, mais n'est pas marquée #[derive(Copy)], deviendra-t-elle Copy ?
Non, un type ne devient pas Copy automatiquement en raison de sa composition — une dérivation explicite Copy est requise pour votre type.
Un type avec des données sur le tas est erronément marqué comme Copy, et une double libération de mémoire se produit lors de la finalisation.
Avantages :
Inconvénients :
Utilisation de Copy pour des structures légères (coordonnées, couleurs), Clone pour des structures complexes (chaînes, vecteurs). Le code est sûr et prévisible.
Avantages :
Inconvénients :