『TRPL Ch 4. Understanding Ownership』

  • 오너십은 러스트의 메모리 관리 방식이다. C에서는 개발자가 직접 메모리를 할당, 해제한다. JVM에서는 가비지 컬렉터가 메모리를 정리한다.
  • 오너십에는 세 가지 규칙이 있다.
    • 각 값은 오너(owner)라고 부르는 변수를 갖는다.
    • 하나의 값은 한 번에 하나의 변수만을 가질 수 있다.
    • 오너가 스코프를 벗어나면 값은 버려진다.
{ // s is not valid here, it’s not yet declared
    let s = "hello"; // s is valid from this point forward
    // do stuff with s
} // this scope is now over, and s is no longer valid

Copy types and Move types

  • 어떤 변수를 다른 변수에 할당할 때 타입에 따라 값이 복사되거나 이동한다.
  • Copy type
    let x = 5;
    let y = x; // y is 5, and x is still valid
    
    • x의 값이 복사되어 y에 할당된다. 이것을 '값이 복사되었다’라고 말한다.
    • 정수, 불리언 등 스택 메모리만을 사용하는 대부분의 원시 타입.
  • Move type
    let s1 = String::from("hello");
    let s2 = s1; // s2 is "hello", and s1 is nolonger valid
    
    • s1이 가리키는 메모리 위치를 s2가 가리키고, s1은 메모리 해제된다. 이것을 '값이 이동했다’라고 말한다.
    • 값을 복사하려면 clone 메소드를 사용해야 한다. (let s2 = s1.clone())
    • 문자열, 벡터 등 비원시 타입.

Ownership and Functions

  • 함수 파라미터로 값을 넘기는 것도 변수에 값을 할당하는 것과 비슷하다.
    • move type을 넘기면 값이 이동한다.
    let s = String::from("hello"); // s comes into scope
    do_something(s); // s's value moves into the function...
    // ... and so is no longer valid here
    
    • copy type을 넘기면 값이 복사된다.
    let x = 5; // x comes into scope
    do_something(x); // x would move into the function,
    // but i32 is Copy, so it’s okay to still
    // use x afterward
    

References and Borrowing

  • 값을 이동시키지 않고 빌려줄 수 있다.
  • 변수의 주소를 참조하는 것이다. 단, 값을 변경할 수는 없다. 이것을 shared borrowing이라고 한다.
    fn main() {
        let a = [1, 2, 3];
        let b = &a;
        println!("{:?} {}", a, b[0]); // [1, 2, 3] 1
    }
    
    fn main() {
        let s1 = String::from("hello");
        let len = calculate_length(&s1);
        println!("The length of '{}' is {}.", s1, len);
    }
    
    fn calculate_length(s: &String) -> usize {
        s.len()
    }
    
    • 여기서 ss1을 참조한다. 함수의 파라미터로 s1의 주소값만 넘기기 때문에 값이 이동하지 않는다.
  • 참조한 데이터를 변경하려면 &mut 키워드가 붙어야 한다. 이것을 mutable borrowing이라고 한다.
    fn main() {
        let mut a = [1, 2, 3];
        let b = &mut a;
        b[0] = 4;
        println!("{:?}", b); // [4, 2, 3]
    }
    
    fn main() {
        let mut s = String::from("hello");
        change(&mut s);
    }
    
    fn change(some_string: &mut String) {
        some_string.push_str(", world");
    }
    
    • 이렇게 하면 change 함수 내에서 some_string을 변경할 때 caller의 s도 변경된다.

이 문서를 인용한 문서