13.2 Ownership and moves
변수들이 자체 자원을 해제할 책임을 갖기 때문에, 자원은 오직 하나의 소유자를 갖는다, 이는 또한 리소스가 한번 이상 해제되는 것을 방지한다. 주목할 점은 모든 변수가 자원을 소유하는건 아니라는 점이다.(예 [참조]).
할당을 수행할 때 (let x = y
)나 함수에 인자를 값으로 전달할 때(foo(x)
), 자원의 소유권은 전달된다. Rust에서는 이를 이동(move)이라고 한다.
자원의 이동 후에, 이전 소유주는 더 이상 사용할 수 없다. 이는 dangling 포인터가 생성되는 것을 회피한다.
// 이 함수는 힙에 할당된 메모리의 소유권을 취한다. fn destroy_box(c: Box<i32>) { println!("Destroying a box that contains {}", c); // `c`는 소멸되고 메모리는 해제된다. } fn main() { // _Stack_ 할당된 정수 let x = 5u32; // `x`를 `y`에 *복사한다* - 리소스의 이동은 없다. let y = x; // 두 값은 독립적으로 사용될 수 있다. println!("x is {}, and y is {}", x, y); // `a`는 _heap_에 할당된 정수에 대한 포인터. let a = Box::new(5i32); println!("a contains: {}", a); // `a`를 `b`로 *옮긴다(Move)* let b = a; // `a`의 포인터 주소가 b로 복사된다(데이터가 아닌). // 이제 둘다 동일한 힙에 할당된 데이터의 포인터지만 // `b`가 현재 소유주이다. // 에러! `a`는 더 이상 데이터에 접근할 수 없게 된다. // 왜냐면, 더 이상 힙 메모리에 대한 소유주가 아니기 때문이다. //println!("a contains: {}", a); // TODO ^ 해당 라인의 주석을 제거해보세요. // 이 함수는 `b`로 부터 힙에 할당된 메모리에 대한 소유권을 취한다. destroy_box(b); // 이 시점에서 힙 메모리가 할당 해제되었기 때문에, // 이 행위는 해제된 메모리에 대한 역참조를 하는 결과를 내겠지만, // 컴파일러에 의해 금지되게 된다. // 에러! 이전 에러와 같은 이유. //println!("b contains: {}", b); // TODO ^ 해당 라인의 주석을 제거해보세요. }