[Rust]6. 소유권(Ownership)
러스트의 꽃이라고 할수 있는 파트가 왔습니다.
메모리 문제를 해결하기 위해, 다른 언어들은 두가지 방법을 활용합니다.
-C,C++같은 언어에서는 직접 할당한것을 직접 수거해주어야합니다.
-Java,Python같은 언어에서는 가비지 컬렉터를 이용합니다.
러스트는 두가지 방법을 모두 쓰지 않고, 소유권(Ownership)이라는 개념을 통해 이를 해결합니다.
소유권 규칙(Ownership rules)
1. 러스트의 모든 값들은 주인(Owner)라 불리는 변수를 갖는다
2. 한 값에 대한 주인은 오직 하나만 존재한다.
3. 주인이 없는 값은 드랍(drop)된다.
물건마다 주인이 있고, 결국 주인없는 물건은 처분한다.
이게 소유권 규칙입니다.
이를 감각적으로 설명하자면 변수를 물건 다루듯 다룬다고 생각하면됩니다.
예를들어 철수가 영희한테 사과를 건네고 나면, 철수는 사과를 먹을수도, 버릴수도 없습니다.
사과를 씹고 뜯고 맛보고 즐길 권한, 안먹고 버릴 권한, 남에게 줄 권한은 전적으로 영희에게 있는 겁니다.
즉, 철수의 사과에 대한 소유권(Ownership)이 영희에게 넘어간 셈입니다. 이를 이동(move)이라 표현합니다.
예를들어 다음과같은 코드가 있다고 칩시다.
let a = "hello";
let b = a;
이 경우, "hello"에 대한 소유권은 a가 선언될때 a가 갖고 있다가, b가 선언되면서 a->b로 그 권한이 이동합니다.
그러면 a는 더이상 사용할수 없게됩니다. 예를들어, println!("{}",a);를 하게되면, 컴파일 에러가 뜹니다.
이 소유권은 값을 할당하거나, 함수의 인수로 값을 넘기거나, 리턴값으로 넘길때 이동(move)합니다.
그리고 이 소유권은 스코프를 벗어날때 사라지고, 메모리가 수거됩니다.(drop).
참고: 러스트에서 스코프는 C와 마찬가지로 중괄호 블럭 내부가 하나의 스코프가 됩니다.
예를 들어, 다음을 봅시다.
fn main()
{
let a = "hello";
let b=AwesomeFunction(a);
}
fn AwesomeFunction->String(str:String)
{
str
}
다만, 이런걸 전혀 신경써줄 필요 없는 것들이 있습니다.
앞서 했던 정수 자료형 (i32,u32 등) 이나, char같은 경우, 그냥 소유권이 이동하지 않고 복사됩니다.
그 이유는 이 자료형들은 스택 영역에만 할당되기 떄문입니다. 이 경우 메모리 관리가 필요 없기에 번거롭게 소유권을 도입하지 않는것입니다.
반면 문자열은 그 크기가 쉽게 변하기 때문에, 정확히 할당하기가 어려워 어쩔수없이 동적할당을 써야합니다. 동적 할당을 하는 이상 메모리 관리는 필수입니다. 그렇기에 문자열에서는 소유권이 존재합니다.