C.W.K.
Stream
Lesson 02 of 05 · published

Move 시맨틱

~12 min · ownership, move, E0382

Level 0Rust 호기심러
0 XP0/80 lessons0/19 achievements
0/100 XP to next level100 XP to go0% complete

모든 새내기의 멘탈 모델을 깨는 줄이 여기 있어 — 그리고 이게 click 하는 순간, Rust 가 click 해.

할당이 move 할 수 있어

대부분 언어에서 let s2 = s1; 은 값을 복사하거나 두 이름이 같은 객체를 가리키게 해. Rust 는 힙 타입에 대해 둘 다 안 해. move 해: 힙 버퍼의 소유권이 s1 에서 s2 로 이전되고 s1 은 무효가 돼. 그 뒤에 s1 을 건드리면 그 유명한 error[E0382]: borrow of moved value 가 떠.

왜 복사 말고 move?

s1s2 가 같은 힙 버퍼를 가리키고 둘 다 스코프 끝에 해제하려 들면 double free 가 나 — 전형적인 C 크래시. Rust 는 구조적으로 막아: move 후엔 s2 만 버퍼를 소유하니까 s2 만 해제해. 두 owner 가 한 할당을 두고 싸우는 시나리오 자체가 없어.

스택 타입은 move 안 해 — 복사해

xi32 일 때 let y = x; 는 값을 복사해, 스택 스칼라 복사는 사소하고 안전하니까 — 그래서 x 는 유효하게 남아. 차이는 임의가 아니야: 복제가 싸고 안전한 타입은 복사하고; 힙 자원을 소유하는 타입은 move 해. 다음 레슨이 그 분리를 명시해.

E0382 'use of moved value' 는 통과의례야. 다들 부딪혀. 컴파일러가 까다로운 게 아니라 — 네가 더는 소유하지 않은 걸 쓰려 한 정확한 순간을 잡는 거야. '두 줄 위에서 이거 넘겨줬잖아' 로 읽어.

진짜 복사본 두 개가 필요하면

.clone() 으로 opt-in 해 — 힙 데이터의 명시적이고 눈에 보이는 깊은 복사. Rust 는 비싼 짓을 절대 조용히 안 해; 깊은 복사가 일어났다면 네가 clone 이라는 단어를 쓴 거야.

Code

Move, 그리고 그게 막는 에러·rust
fn main() {
    let s1 = String::from("hello");
    let s2 = s1;          // 소유권이 s1 에서 s2 로 MOVE 됨

    // println!("{s1}");  // error[E0382]: borrow of moved value: `s1`
    println!("{s2}");     // 이제 s2 가 유일한 owner — 괜찮음

    // 스택 스칼라는 move 대신 복사:
    let x = 5;
    let y = x;            // x 는 move 가 아니라 COPY 됨
    println!("{x} {y}");  // 둘 다 유효
} // s2 의 버퍼만 해제됨 — double free 불가능

External links

Exercise

String 을 한 변수에서 다른 변수로 move 하는 두 줄을 쓰고 원본을 출력해봐. E0382 에러를 읽어. 이제 두 방법으로 컴파일되게 해: 먼저 .clone() 으로, 그다음엔 그냥 새 owner 를 출력하는 걸로. 어느 쪽이 실제로 메모리를 더 할당해?
Hint
.clone() 은 힙 버퍼를 깊은 복사하고; 새 owner 출력은 아무것도 복사 안 해. 진짜로 독립된 복사본 두 개가 필요할 때만 clone 으로 손 뻗어.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고
💛 by 똘이warm

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.