소유권 관련 개념들...

코와->코어·2022년 5월 4일
0

Ownership

러스트에서, 값을 할당받은 변수는 그 값의 소유자가 됨

let v: Vec<i32> = Vec::new();
  • 변수 v는 i32 타입의 벡터 인스턴스의 소유자임

변수가 범위({}사이)를 벗어나면 소유하고 있는 값은 드롭(memory free/return)
소유자는 한 순간에 한 명만 존재
-> 즉, 오직 소유자만이 해당 변수를 드롭시킬 수 있음(double-free bug 방지)

let v: Vec<i32> = Vec::new();
let v1 = v;//v1 is the new owner
v.len();//error: Use of moved value
  • v에 할당되어 있던 Vec 인스턴스를 v1으로 옮기면, 소유권도 v1에게로 넘어감
    -> 2번째 줄 이후부터 Vec에 접근하려면, v가 아니라 v1을 통해 접근해야 함

Borrowing

근데 소유자만 해당 변수에 할당된 값을 다룰 수 있다면 너무 빡빡함! 프로그래밍 하기 힘듦!

그래서 소유자로부터 참조를 빌릴 수 있는 borrowing이라는 개념이 있음

소유자는 한 순간에 오직 한 명만 있어야 하지만, borrower는 한 순간에 여러 명이 있을 수 있음

let v: Vec<i32> = Vec::new();
let v1 = &v;//v1 has borrowed from v
let v2 = &v;//v2 has also borrowed from v
v.len();//allowed
v1.len();//also allowed
v2.len();//also allowed

대신 소유자가 그 값을 드롭하면, borrower도 그 값에 접근할 수 없음(use-after-free bug 방지)

let v1: &Vec<i32>;
{
   let v = Vec::new();
   v1 = &v;
}//v is dropped here
v1.len();//error:borrowed value does not live long enough

Mutable Borrowing

동시에 여러 개의 참조가 존재할 수 있지만, 변경가능한 참조는 한 순간에 하나만 있어야 함

let mut v = vec![0, 1, 2, 3];
let v1 = &v[0];//an immutable reference to Vec's first element
v.push(4);//this can invalidate Vec's internal buffer
let v2 = *v1;//this could access invalid memory

Lifetime

러스트는 컴파일 타임에 변수들의 라이프타임을 추적함
non-lexical lifetime이라고, 복잡하게 구현됨!

참조

Move

소유권 이동

let v:Vec<i32> = Vec::new();
let v1 = v;//v1 is the new owner

Vec은 동적인 자료구조이기 때문에 Heap영역에 메모리를 할당받음

더 정확하게 말하자면,
Vec은 {실제 요소가 저장되어 있는 주소/사용가능한 용량/사용중인 용량}을 가리키는 버퍼(포인터) 값이고, 이 버퍼는 스택에 저장됨
실제 요소가 저장되어 있는 곳이 Heap임

위 코드에서처럼 Vec 인스턴스의 소유권을 v1이라는 다른 변수로 이동시키면
스택에 버퍼가 복사된다. 이때, v1만이 heap의 메모리를 드롭시킬 수 있고 v로는 접근할 수 없음

이렇게 함으로써 두 주체(v, v1)가 힙 메모리를 드롭시킬 수 없게 되었다.

소유권 이동은 다른 변수로의 할당, 함수에 인자를 넘길 때, 함수로부터 리턴값을 받을 때, 구조체나 enum의 필드에 값을 할당할 때 일어난다.

Copy

복사

값이 힙에 할당되지 않는 변수들.
정확히 말하면 Copy trait을 구현하고 있는 타입들


두 변수는 완전히 독립적임

Clone

소유권을 이동시키지 않고 진짜로 deep copy를 하고 싶다면?

let v: Vec<i32> = Vec::new();
let v1 = v.clone();//ok since Vec implements Clone
println!("v's length is {}", v.len());//ok

Clone trait을 구현하면 됨


참조

profile
풀스택 웹개발자👩‍💻✨️

0개의 댓글