paint-brush
Références mutables ou variables mutables ? Décoder le mut-mut-mut de Rustpar@charnog
904 lectures
904 lectures

Références mutables ou variables mutables ? Décoder le mut-mut-mut de Rust

par Denis Gonchar5m2023/09/23
Read on Terminal Reader

Trop long; Pour lire

La sécurité de la mémoire de Rust repose sur ses mécanismes de propriété et d'emprunt. Cet article explore les subtilités du mot-clé mut, en faisant la distinction entre les références mutables et les variables mutables. Le point clé à retenir ? Tous les mutants ne sont pas créés égaux : les références mutables permettent de modifier la valeur pointée, tandis que les variables mutables avec des références peuvent changer l'endroit où elles pointent. Une astuce de visualisation pratique utilisant le signe = simplifie la compréhension de ces distinctions.
featured image - Références mutables ou variables mutables ? Décoder le mut-mut-mut de Rust
Denis Gonchar HackerNoon profile picture

Introduction

Même si Rust fournit son livre Rust, j'ai eu du mal à comprendre le mot-clé mut . Je me suis demandé : « Suis-je le seul à avoir ce problème ? » Une recherche rapide sur Google a confirmé que je n'étais pas seul.


En conséquence, j'ai décidé d'écrire cet article pour fournir une explication détaillée du mot-clé mut . Cet article est destiné à ceux qui proviennent de langages de haut niveau comme Python ou JavaScript.

Les variables

Pour créer une variable non modifiable dans Rust, écrivez simplement let x = 1337 . C'est simple. Si vous souhaitez créer une variable qui pourra être mutée ultérieurement, ajoutez simplement le mot-clé mut après let . Rust a une convention utile qui encourage la clarté des intentions.


L'ajout du mot-clé mut informe les autres que cette variable sera modifiée ailleurs dans le code. D'accord.


Visualisons-le. Deux variables ici, let mut x = 1337 et let y = 42 .

Prénom; deuxième - type, troisième - valeur, quatrième - drapeau mut.

Les references

Pour le moment, tout est simple. Cependant, les choses commencent à devenir un peu bouclées lors de l'utilisation de références mut . Créons-en.

 let mut x = 1337; let y = 42; let x_ref = &mut x; let y_ref = &y;


J'ai créé deux références (ou "empruntées" en terme de Rust). L'un d'eux est une référence mutable et l'autre est une référence en lecture seule. Créons à nouveau un schéma pour cela.


Dans le schéma donné, j'ai 4 variables, dont 2 sont des références. Les deux variables de référence sont immuables et n'ont pas de mot-clé mut après let , ce qui signifie que je ne peux pas changer ce vers quoi elles pointent. Cependant, je peux toujours modifier la valeur à laquelle ils font référence.

 *x_ref = 777;


Si vous écrivez ceci, le compilateur Rust ne se plaindra pas et la valeur de x (pas la référence elle-même) deviendra 777 . Cependant, il y a un carré rouge sur le schéma indiquant que x_ref ne dispose pas de l'option de mutabilité. Alors, pourquoi puis-je modifier la valeur à laquelle elle fait référence ?


Revenons au schéma du let x_ref = &mut x .


Le premier bloc blanc contient le nom : x_ref . Le second m'informe sur le type stocké dans cette variable. Dans sa forme complète, sans aucune annotation de type implicite, je peux écrire ce qui suit :

 let x_ref: &mut i32 = &mut x;


Je peux interpréter cela comme : créons une variable immuable nommée x_ref qui contiendra une référence mutable à i32 et initialisons-la immédiatement avec la référence mutable à la valeur i32 dans la variable x .


Cela signifie que je peux modifier la valeur vers laquelle elle pointe, mais je ne peux pas modifier la valeur (ou l'adresse) de la référence. En d'autres termes, je ne peux pas écrire quelque chose comme :

 let x_ref: &mut i32 = &mut x; let mut z = 0; x_ref = &mut z; // Not allowed!


En termes de schémas, je souhaite changer la direction vers laquelle pointe la flèche dans le bloc de code ci-dessus. Cependant, même si la variable z est mutable, je ne peux pas changer la flèche car le problème réside dans l'immuabilité de la x_ref elle-même.


Pour changer le sens de la flèche, je dois modifier l'adresse stockée dans la variable x_ref . Cependant, je ne peux pas le faire car la variable est immuable.


Faisons-le!

 let mut x: i32 = 1337; let mut x_ref: &mut i32 = &mut x; // I've added mut before x_ref let mut z = 0; x_ref = &mut z; // Allowed!


Il y a trop d'instances de mut ici autour x_ref , n'est-ce pas ? Décrivons-les.


  1. let mut x_ref : je crée une variable mutable nommée x_ref , ce qui signifie que je peux modifier sa valeur plus tard.


  2. &mut i32 : je déclare que la variable contiendra une ou plusieurs références mutables à une valeur de type i32 .


  3. &mut x : j'emprunte (obtiens une référence à) la variable x .


Ensuite, j'ai créé une variable nommée z et lui ai attribué la valeur 0 . Par la suite, lorsque j'ai écrit x_ref = &mut z , j'ai indiqué que je comprenais que x_ref était une variable mutable qui ne pouvait contenir que des références à des valeurs i32 .


Puisque le type de z est i32 , je peux attribuer son adresse à la variable x_ref . Pour obtenir l'adresse de z , j'ai utilisé la syntaxe &mut z .


Le schéma.

L'astuce mentale

Jetez un oeil à = dans la déclaration, cela peut paraître un peu évident, mais…

 let mut x_ref = &mut x;


… Je le vois comme un diviseur (surtout si vous le faites pivoter de 90 degrés) qui divise l'instruction en deux sous-instructions : gauche et droite. Le côté gauche fournit des informations sur la variable elle-même, tandis que le côté droit nous renseigne sur la valeur .


Lorsque j'utilise l'opérateur de déréférencement * pour modifier la valeur...

 *x_ref = 100;

... Je ne change pas la valeur de la variable x_ref . Au lieu de cela, je modifie la valeur à laquelle x_ref fait référence.

Références immuables

J'utilisais fréquemment mut auparavant. Et si j’en oublie certains ?

 let i = 1; let j = 2; let mut k = &i;


Puis-je changer la valeur de i ici ? En utilisant la technique du diviseur, il est assez simple de répondre. Je peux changer la valeur de k (je vois mut sur le côté gauche), mais la valeur (côté droit) est une référence immuable à i (il n'y a pas mut ici).


Donc…

 let i = 1; let j = 2; let mut k = &i; k = &j; // This is legal. *k = 3; // This is not.


Le schéma.

Conclusion

Dans cet article, nous avons disséqué les nuances du mot-clé et des références mut . N'oubliez pas qu'il existe une distinction entre une référence mutable et une variable mutable contenant une référence. Notre astuce ?


Utiliser le signe = comme diviseur mental pour mieux comprendre les missions dans Rust. Cette simple visualisation peut dissiper de nombreuses confusions.


Bon codage !