Rust가 Rust 책을 제공했음에도 불구하고 나는 mut
키워드를 이해하는 데 어려움을 겪었습니다. 나는 "나만 이런 문제를 겪고 있는 걸까?"라고 자문했다. 빠른 Google 검색을 통해 내가 혼자가 아님을 확인했습니다.
그 결과, mut
키워드에 대한 자세한 설명을 제공하기 위해 이 글을 쓰기로 결정했습니다. 이 글은 Python이나 JavaScript와 같은 고급 언어를 사용하는 사람들을 대상으로 작성되었습니다.
Rust에서 변경할 수 없는 변수를 만들려면 간단히 let x = 1337
이라고 작성하세요. 그것은 간단합니다. 나중에 변경할 수 있는 변수를 생성하려면 let
뒤에 mut
키워드를 추가하면 됩니다. Rust에는 의도의 명확성을 장려하는 유용한 규칙이 있습니다.
mut
키워드를 추가하면 이 변수가 코드의 다른 곳에서 수정될 것임을 다른 사람에게 알립니다. 좋아요.
시각화해보자. 여기에는 두 개의 변수가 있습니다. let mut x = 1337
이고 let y = 42
.
현재로서는 모든 것이 간단합니다. 그러나 mut
참조를 사용하면 상황이 약간 복잡해지기 시작합니다. 몇 가지를 만들어 보겠습니다.
let mut x = 1337; let y = 42; let x_ref = &mut x; let y_ref = &y;
나는 두 개의 참조를 만들었습니다(또는 Rust의 관점에서 "빌려온"). 그 중 하나는 변경 가능한 참조이고 다른 하나는 읽기 전용 참조입니다. 이에 대한 계획을 다시 만들어 보겠습니다.
주어진 구성표에는 4개의 변수가 있으며 그 중 2개는 참조입니다. 두 참조 변수 모두 불변이며 let
뒤에 mut
키워드가 없습니다. 이는 그들이 가리키는 것을 변경할 수 없음을 의미합니다. 그러나 참조하는 값을 변경할 수는 있습니다.
*x_ref = 777;
이것을 작성하면 Rust 컴파일러는 불평하지 않고 x
값(ref 자체가 아님)이 777
로 변경됩니다. 그러나 x_ref
에 가변 옵션이 없음을 나타내는 구성표에 빨간색 사각형이 있습니다. 그렇다면 그것이 참조하는 값을 왜 변경할 수 있습니까?
let x_ref = &mut x
에 대한 계획으로 다시 돌아가 보겠습니다.
첫 번째 흰색 블록에는 x_ref
라는 이름이 포함되어 있습니다. 두 번째는 해당 변수에 저장된 유형에 대해 알려줍니다. 암시적인 유형 주석 없이 완전한 형태로 다음과 같이 작성할 수 있습니다.
let x_ref: &mut i32 = &mut x;
나는 이것을 다음과 같이 해석할 수 있습니다: i32
에 대한 변경 가능한 참조를 보유하고 x
변수의 i32
값에 대한 변경 가능한 참조 로 즉시 초기화하는 x_ref
라는 불변 변수를 생성해 보겠습니다.
즉, 참조 값(또는 주소)은 변경할 수 없지만 참조 값은 수정할 수 있습니다. 즉, 다음과 같은 내용을 작성할 수 없습니다.
let x_ref: &mut i32 = &mut x; let mut z = 0; x_ref = &mut z; // Not allowed!
구성표 측면에서 위의 코드 블록에서 화살표가 가리키는 방향을 변경하고 싶습니다. 그러나 z
변수가 변경 가능하더라도 문제는 x_ref
자체의 불변성에 있기 때문에 화살표를 변경할 수 없습니다.
화살표 방향을 바꾸려면 x_ref
변수에 저장된 주소를 수정해야 합니다. 그러나 변수가 불변이기 때문에 이 작업을 수행할 수 없습니다.
해보자!
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!
x_ref
주변에는 mut
인스턴스가 너무 많습니다. 그렇죠? 그것들을 설명해 봅시다.
let mut x_ref
: x_ref
라는 변경 가능한 변수를 생성 중입니다. 이는 나중에 해당 값을 변경할 수 있음을 의미합니다.
&mut i32
: 변수에 i32
유형의 일부 값에 대한 변경 가능한 참조가 포함된다는 점을 명시하고 있습니다.
&mut x
: 변수 x
차용(참조 가져오기)합니다.
그런 다음 z
라는 변수를 만들고 여기에 0
값을 할당했습니다. 나중에 x_ref = &mut z
작성할 때 x_ref
i32
값에 대한 참조만 보유할 수 있는 변경 가능한 변수라는 것을 이해했음을 표시했습니다.
z
의 유형이 i32
이므로 해당 주소를 x_ref
변수에 할당할 수 있습니다. z
의 주소를 얻기 위해 &mut z
구문을 사용했습니다.
계획.
명령문에서 =
살펴보세요. 약간 뻔해 보일 수도 있지만…
let mut x_ref = &mut x;
… 나는 그것을 진술을 두 개의 하위 진술, 즉 왼쪽과 오른쪽으로 나누는 구분선(특히 90도 회전하는 경우)으로 봅니다. 왼쪽은 변수 자체에 대한 정보를 제공하고 오른쪽은 값에 대한 정보를 제공합니다.
*
역참조 연산자를 사용하여 값을 변경하면...
*x_ref = 100;
... x_ref
변수의 값을 변경하지 않습니다. 대신 x_ref
가 참조하는 값을 변경합니다.
이전에는 mut
자주 사용했습니다. 그 중 일부를 생략하면 어떻게 되나요?
let i = 1; let j = 2; let mut k = &i;
여기서 i
의 값을 변경할 수 있나요? 구분선 기술을 사용하면 대답하기가 매우 간단합니다. k
의 값을 변경할 수 있지만(왼쪽에 mut
표시됨) 값(오른쪽)은 i
에 대한 불변 참조입니다(여기에는 mut
가 없습니다).
그러므로…
let i = 1; let j = 2; let mut k = &i; k = &j; // This is legal. *k = 3; // This is not.
계획.
이 글에서는 mut
키워드와 참조의 미묘한 차이를 분석했습니다. 변경 가능한 참조 와 참조를 보유하는 변경 가능한 변수 사이에는 차이가 있다는 점을 기억하세요. 우리의 트릭?
Rust의 할당을 더 잘 이해하기 위해 =
기호를 정신적 구분자로 사용합니다. 이 간단한 시각화를 통해 많은 혼란을 해결할 수 있습니다.
즐거운 코딩하세요!