Rust에서 의미 체계 이동

Nilesh Katuwal 2022년6월7일
Rust에서 의미 체계 이동

이 기사에서 우리는 Rust의 이동 의미에 대해 배울 것입니다.

Rust에서 의미 체계 이동

Rust에서 모든 유형은 변경 가능하고 모든 이동 작업은 새 위치에 있는 원본 데이터의 비트 복사본과 동일합니다. 이동은 캡처된 모든 변수를 참조로 변환하거나 변경 가능한 참조로 캡처한 변수를 값으로 변환합니다.

스레드가 관련된 경우 이동이 일반적으로 사용됩니다.

녹 제거 과정도 파괴적입니다. 예를 들어, 변수를 떠난 후에는 해당 변수를 더 이상 코드에서 사용할 수 없습니다.

Rust에서 이동은 원래 객체를 파괴하지 않고 객체 자체의 데이터를 복사하여 일관되게 구현됩니다. 개체의 관리 리소스를 복사하거나 사용자 지정 코드를 실행하여 구현되지 않습니다.

Rust는 이동 의미 체계가 필요하지 않은 유형에 대해 예외를 만듭니다. 대신 값에는 값을 나타내는 데 필요한 모든 정보가 포함되며 i32와 같은 값은 힙 할당이나 리소스를 관리하지 않습니다.

이러한 유형은 복사가 저렴하고 함수에 전달하거나 할당을 관리하는 기본 방법이기 때문에 특별한 Copy 특성을 구현합니다.

fn foo(bar: i32) {
    // Implementation
}

let var: i32 = 9;
foo(var); // copy
foo(var); // copy
foo(var); // copy

기본 함수 호출은 String과 같은 Copy 이외의 유형에 대해 이동 의미 체계를 사용합니다. Rust에서 변수가 이동되면 수명이 조기에 종료됩니다.

컴파일 타임에 이동은 블록 끝에서 소멸자 호출을 대체하므로 String에 대해 다음 코드를 작성하는 것은 오류입니다.

fn foo(bar: String) {
    // Implementation
}

let var: String = "Hello".to_string();
foo(var); // Move
foo(var); // Compile-Time Error
foo(var); // Compile-Time Error

복제 녹은 구현이 필요하지만 모든 이동에 대해 동일합니다. 값의 메모리를 복사하고 원래 값의 소멸자를 호출하지 않습니다.

그리고 Rust에서는 이 정확한 구현으로 모든 유형을 이동할 수 있습니다. 움직일 수 없는 유형은 존재하지 않습니다(비이동 가능한 값은 있지만). 바이트는 포인터와 같이 값이 관리하는 리소스에 대한 정보를 이전 위치에서와 마찬가지로 효과적으로 새 위치에서 인코딩해야 합니다.

Rust에는 유형 시스템에서 특정 값이 다시는 이동하지 않을 것임을 나타내는 고정(pinning)이라는 메커니즘이 있습니다. 이 메커니즘은 자체 참조 값을 구현하는 데 사용할 수 있고 비동기식으로 활용됩니다.

예시:

fn destroy_box(z: Box<i32>) {
    println!("The box that contains {} is destroyed", z);
}

fn main() {
    let a = 5u32;
    let b = a;
    println!("a is {}, and y is {}", a, b);

    let m = Box::new(5i32);

    println!("a contains: {}", m);
    let n = m;
    destroy_box(n);
}

destroy_box 함수는 위 소스 코드에서 힙 할당 메모리의 소유권을 가져옵니다. 먼저 z가 파괴되고 메모리가 해제됩니다.

m은 힙 할당 정수에 대한 포인터입니다.

출력:

a is 5, and y is 5
a contains: 5
The box that contains 5 is destroyed