Salut,
ref te permet d’emprunter la variable, tu n’en es donc pas propriétaire, mais le type reste le même, alors que & a un type différent.
Ça n’a absolument aucun sens. Si le type restait le même, l’état d’ownership serait aussi le même… Il n’y a pas de différence entre let u = &c
et let ref u = c
, dans les deux cas on se retrouve avec u
qui est une référence vers c
.
Quand on a déjà un binding vers une valeur (comme c
) et qu’on veut une référence vers cette valeur, on préfère utiliser &c
pour construire la référence (la forme let ref u = c
est d’ailleurs levée par clippy
comme étant non-idiomatique). ref u
est utile lorsqu’on fait du pattern matching plus avancé et qu’on veut directement obtenir une référence à partir d’une valeur owned. Par exemple :
let a = Some(5u8);
if let Some(ref b) = a {}
permet d’obtenir b
comme une référence &u8
vers le 5
contenu dans a
.
Quant à Rc, il s’agit de partager une ressource. Par exemple, disons que tu as une classe de sortie audio, et que tu as plusieurs classes de source audio, tu ne vas instancier qu’une seule fois ta sortie audio et la partager entre les sources pour qu’ils y aient accès et se partage la propriété. Ainsi, tant qu’une de ces sources existent (autrement dit tant que tu utilises ta sortie audio), l’instance de ta sortie audio existera. Quand toutes les sources seront détruites, ta sortie audio aussi.
Il n’y a pas de classes en Rust… Ensuite, pour partager une ressource, on a déjà des références qui sont garanties valides. Pour être moins flou, le but de Rc
est de déplacer la question de la résolution des lifetimes au runtime plutôt qu’au compile time. On parle parfois de shared owernship, parce que plutôt que d’avoir un seul propriétaire d’une ressource quelconque qui contrôle statiquement sa durée de vie et plein de références simples, on wrappe cette ressource dans un Rc
qu’on peut ensuite cloner à loisir. Quand on clone un Rc
, on se retrouve en apparence avec une nouvelle valeur qui nous appartient complètement, mais en fait la ressource n’est pas clonée en mémoire. Chaque Rc
est un pointeur vers la même zone mémoire, et la résolution de la durée de vie de la ressource pointée se fait au runtime lorsque le dernier Rc
disparaît. C’est très utile lorsqu’une ressource est partagée entre plein d’acteurs et qu’avoir un seul propriétaire et des références simples conduirait à un code beaucoup plus compliqué (voire tout simplement impossible à écrire).