『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() }
- 여기서
s
는s1
을 참조한다. 함수의 파라미터로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
도 변경된다.
- 이렇게 하면