Obwohl Rust sein Rust-Buch bereitstellt, hatte ich Schwierigkeiten, das Schlüsselwort mut
zu verstehen. Ich fragte mich: „Bin ich der Einzige, der dieses Problem hat?“ Eine schnelle Google-Suche bestätigte, dass ich nicht allein war.
Aus diesem Grund habe ich beschlossen, diesen Artikel zu schreiben, um eine detaillierte Erklärung des Schlüsselworts mut
zu geben. Dieser Artikel richtet sich an diejenigen, die mit Hochsprachen wie Python oder JavaScript arbeiten.
Um eine unveränderliche Variable in Rust zu erstellen, schreiben Sie einfach let x = 1337
. Es ist unkompliziert. Wenn Sie eine Variable erstellen möchten, die später mutiert werden kann, fügen Sie einfach das Schlüsselwort mut
nach let
hinzu. Rust hat eine hilfreiche Konvention, die die Klarheit der Absichten fördert.
Durch das Hinzufügen des Schlüsselworts mut
werden andere darüber informiert, dass diese Variable an einer anderen Stelle im Code geändert wird. Okay.
Lass es uns visualisieren. Zwei Variablen hier, let mut x = 1337
und let y = 42
.
Im Moment ist alles unkompliziert. Bei der Verwendung mut
Referenzen wird es jedoch etwas komplizierter. Lassen Sie uns welche erstellen.
let mut x = 1337; let y = 42; let x_ref = &mut x; let y_ref = &y;
Ich habe zwei Referenzen erstellt (oder im Sinne von Rust „geliehen“). Eine davon ist eine veränderbare Referenz und die andere ist eine schreibgeschützte Referenz. Lassen Sie uns dafür noch einmal ein Schema erstellen.
Im angegebenen Schema habe ich 4 Variablen, von denen 2 Referenzen sind. Beide Referenzvariablen sind unveränderlich und haben nach let
nicht das Schlüsselwort mut
, was bedeutet, dass ich nicht ändern kann, worauf sie verweisen. Allerdings kann ich den Wert, auf den sie verweisen, immer noch ändern.
*x_ref = 777;
Wenn Sie dies schreiben, wird sich der Rust-Compiler nicht beschweren und der Wert von x
(nicht der Verweis selbst) ändert sich in 777
. Es gibt jedoch ein rotes Quadrat im Schema, das darauf hinweist, dass x_ref
die Veränderlichkeitsoption fehlt. Warum kann ich also den Wert ändern, auf den es sich bezieht?
Kommen wir zurück zum Schema für let x_ref = &mut x
.
Der erste weiße Block enthält den Namen: x_ref
. Der zweite informiert mich über den in dieser Variablen gespeicherten Typ. In seiner vollständigen Form, ohne implizite Typanmerkungen, kann ich wie folgt schreiben:
let x_ref: &mut i32 = &mut x;
Ich kann das so interpretieren: Lassen Sie uns eine unveränderliche Variable namens x_ref
erstellen, die einen veränderlichen Verweis auf i32
enthält, und sie sofort mit dem veränderlichen Verweis auf den i32
-Wert in der x
Variablen initialisieren.
Das bedeutet, dass ich den Wert ändern kann, auf den es zeigt, aber ich kann den Wert (oder die Adresse) der Referenz nicht ändern. Mit anderen Worten, ich kann nicht so etwas schreiben wie:
let x_ref: &mut i32 = &mut x; let mut z = 0; x_ref = &mut z; // Not allowed!
In Bezug auf die Schemata möchte ich die Richtung ändern, in die der Pfeil im obigen Codeblock zeigt. Selbst wenn die z
Variable veränderbar ist, kann ich den Pfeil jedoch nicht ändern, da das Problem in der Unveränderlichkeit von x_ref
selbst liegt.
Um die Pfeilrichtung zu ändern, muss ich die in der Variablen x_ref
gespeicherte Adresse ändern. Dies kann ich jedoch nicht tun, da die Variable unveränderlich ist.
Lass es uns tun!
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!
Es gibt hier rund um x_ref
zu viele mut
-Instanzen, oder? Beschreiben wir sie.
let mut x_ref
: Ich erstelle eine veränderbare Variable mit dem Namen x_ref
, was bedeutet, dass ich ihren Wert später ändern kann.
&mut i32
: Ich behaupte, dass die Variable veränderbare Verweise auf einen Wert vom Typ i32
enthalten wird.
&mut x
: Ich leihe mir die Variable x
aus (erhalte einen Verweis darauf).
Dann habe ich eine Variable namens z
erstellt und ihr den Wert 0
zugewiesen. Als ich später x_ref = &mut z
schrieb, gab ich an, dass ich x_ref
als eine veränderliche Variable verstehe, die nur Verweise auf i32
Werte enthalten kann.
Da der Typ von z
i32
ist, kann ich seine Adresse der Variablen x_ref
zuweisen. Um die Adresse von z
zu erhalten, habe ich die Syntax &mut z
verwendet.
Das Schema.
Schauen Sie sich =
in der Anweisung an, es sieht vielleicht etwas offensichtlich aus, aber ...
let mut x_ref = &mut x;
… Ich sehe es als einen Teiler (besonders wenn man ihn um 90 Grad dreht), der die Aussage in zwei Unteraussagen aufteilt: links und rechts. Die linke Seite liefert Informationen über die Variable selbst, während die rechte Seite uns über den Wert informiert.
Wenn ich den Dereferenzierungsoperator *
verwende, um den Wert zu ändern ...
*x_ref = 100;
... Ich ändere den Wert der x_ref
Variablen nicht. Stattdessen ändere ich den Wert, auf den x_ref
verweist.
Ich habe mut
vorher häufig verwendet. Was ist, wenn ich einige davon weglasse?
let i = 1; let j = 2; let mut k = &i;
Kann ich den Wert von i
hier ändern? Mit der Divider-Technik ist die Antwort recht einfach. Ich kann den Wert von k
ändern (ich sehe mut
auf der linken Seite), aber der Wert (rechte Seite) ist eine unveränderliche Referenz auf i
(hier gibt es kein mut
).
Daher…
let i = 1; let j = 2; let mut k = &i; k = &j; // This is legal. *k = 3; // This is not.
Das Schema.
In diesem Artikel haben wir die Nuancen des Schlüsselworts mut
und der Referenzen analysiert. Denken Sie daran, dass es einen Unterschied zwischen einer veränderlichen Referenz und einer veränderlichen Variablen gibt, die eine Referenz enthält. Unser Trick?
Verwenden des =
-Zeichens als mentale Trennlinie, um Aufgaben in Rust besser zu verstehen. Diese einfache Visualisierung kann viele Verwirrungen beseitigen.
Viel Spaß beim Codieren!