paint-brush
가변 참조 또는 가변 변수? Rust의 mut-mut-mut 디코딩~에 의해@charnog
904 판독값
904 판독값

가변 참조 또는 가변 변수? Rust의 mut-mut-mut 디코딩

~에 의해 Denis Gonchar5m2023/09/23
Read on Terminal Reader
Read this story w/o Javascript

너무 오래; 읽다

Rust의 메모리 안전성은 소유권과 차용 메커니즘에 뿌리를 두고 있습니다. 이 기사에서는 가변 참조와 가변 변수를 구별하여 mut 키워드의 복잡성을 자세히 살펴봅니다. 핵심 내용은 무엇입니까? 모든 mut가 동일하게 생성되는 것은 아닙니다. 가변 참조를 사용하면 가리키는 값을 변경할 수 있지만 참조가 있는 가변 변수는 가리키는 위치를 변경할 수 있습니다. = 기호를 사용한 편리한 시각화 트릭을 사용하면 이러한 차이점을 쉽게 이해할 수 있습니다.
featured image - 가변 참조 또는 가변 변수? Rust의 mut-mut-mut 디코딩
Denis Gonchar HackerNoon profile picture

소개

Rust가 Rust 책을 제공했음에도 불구하고 나는 mut 키워드를 이해하는 데 어려움을 겪었습니다. 나는 "나만 이런 문제를 겪고 있는 걸까?"라고 자문했다. 빠른 Google 검색을 통해 내가 혼자가 아님을 확인했습니다.


그 결과, mut 키워드에 대한 자세한 설명을 제공하기 위해 이 글을 쓰기로 결정했습니다. 이 글은 Python이나 JavaScript와 같은 고급 언어를 사용하는 사람들을 대상으로 작성되었습니다.

변수

Rust에서 변경할 수 없는 변수를 만들려면 간단히 let x = 1337 이라고 작성하세요. 그것은 간단합니다. 나중에 변경할 수 있는 변수를 생성하려면 let 뒤에 mut 키워드를 추가하면 됩니다. Rust에는 의도의 명확성을 장려하는 유용한 규칙이 있습니다.


mut 키워드를 추가하면 이 변수가 코드의 다른 곳에서 수정될 것임을 다른 사람에게 알립니다. 좋아요.


시각화해보자. 여기에는 두 개의 변수가 있습니다. let mut x = 1337 이고 let y = 42 .

이름; 두 번째 - 유형, 세 번째 - 값, 네 번째 - mut 플래그입니다.

참고자료

현재로서는 모든 것이 간단합니다. 그러나 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 인스턴스가 너무 많습니다. 그렇죠? 그것들을 설명해 봅시다.


  1. let mut x_ref : x_ref 라는 변경 가능한 변수를 생성 중입니다. 이는 나중에 해당 값을 변경할 수 있음을 의미합니다.


  2. &mut i32 : 변수에 i32 유형의 일부 값에 대한 변경 가능한 참조가 포함된다는 점을 명시하고 있습니다.


  3. &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의 할당을 더 잘 이해하기 위해 = 기호를 정신적 구분자로 사용합니다. 이 간단한 시각화를 통해 많은 혼란을 해결할 수 있습니다.


즐거운 코딩하세요!