본문 바로가기

Rust

소유권

[1. 개요]

가비지 컬렉터 없이 메모리 안정성을 보장하게 해준다.

메모리는 컴파일 타임에 컴파이럴가 체크할 규칙들로 구성된 소유권 시스템을 통해 관리된다.

소유권 기능들의 그 어떤 것도 런타임 비용이 발생하지 않는다.

 

러스트 같은 시스템 프로그래밍 언어에서는 

값이 스택에 있는지 힙에 있는지 여부가 언어의 동작 방식에 더 큰 영향을 준다.

 

스택은 데이터에 접근하는 방식때문에 빠르다.

새로운 데이터를 넣어두기 위한 혹은 데이터를 가져올 공간을 검색 할 필요가 없기 때문이며,

스택에 담긴 모든 데이터는 고정된 크기를 갖고 있다.

 

컴파일 타임에 크기가 결정되지 않거나, 변경될 수 있는 데이터는 힙에 저장된다.

힙 할당은 스택보다 복잡하여 스택보다 느리다.

 

따라서 코드의 어느 부분이 힙의 어떤 데이터를 사용하는지 추적하는 것, 

힙 의 중복 된 데이터의 양을 최소화 하는 것,

힙 내에 사용하지 않는 데이터를 제거하여 공간이 모자라지 않게 하는 것은

모두 소유권과 관계된 문제들이다.

(힙 영역 데이터에 대한 소유권?)

 

 

[2. 소유권 규칙]

1. Rust 의 각각의 값은 해당 값의 Owner 라고 불리우는 변수가 갖는다.

2. 한번에 딱 하나의 Owner 만 존재 할 수 있다.
=> 값은 단 하나의 Owner 만 소유 할 수 있다.

3. Owner 가 scope 밖으로 벗어날 때, 값은 버려진다.

 

 

[3. String 타입]

이전에 봐온 데이터 타입들은 스택에 저장되었다가 scope 를 벗어 날 때 스택으로 부터 버려진다.

=> scalar type, tuple, array 는 컴파일 시점에 그 크기를 알 수 있다.

 

문자열 값(리터럴 문자열) 은 immutable 하다.

또, 모든 문자열이 우리가 프로그래밍하는 시점에서 알 수 없기 때문이다.

 

그러나 String::from() 을 사용하여, 힙에 문자열을 할당 할 수 있다.

또, push_str() 함수를 이용하여 문자열 변경이 가능하다.

(단, 이 경우 mut 변수 이어야 한다.)

해당 문자열은 scope 를 벗어 났을 시, 메모리 공간이 알아서 반납된다.

 

변수가 scope 밖으로 벗어나면, Rust 는 drop 이라 부르는 특별한 함수를 호출

이 함수는 drop() 이라는 함수로, String 의 메모리를 반납하는 코드를 작성 할 수 있다.

 

 

변수와 데이터간 상호작용 => 이동(move)

 

case1

let x = 5;
let y = x;

변수 x 에 저장된 값이, 변수 y 에도 복사된다.

이는, 변수의 크기를 컴파일 시간에 알 수 있어, 스택에 저장 할 수 있기 때문이다.

 

case2

let s1 = String::from("hello");
let s2 = s1;

String::from() 은 힙 영역에 데이터를 저장 한다.

그래서, 힙 영역에 데이터를 복사하기 보다는, 힙 영역 데이터의 소유권을 s2 로 넘긴다.

(두 변수 모두 같은 힙 영역을 가리키면, double free 가 발생 할 수 있다.)

따라서 s1 이 소유권을 s2 로 넘긴 후 에는 s1 을 사용 할 수 없다.

 

 

변수와 데이터간 상호작용 => 클론

 

힙 영역 데이터를 깊이 복사하고자 한다면, 

clone() 이라는 공용 메소드를 사용 할 수 있다.

let s1 = String::from("hello");
let s2 = s1.clone();

println!("s1 = {}, s2 = {}", s1, s2);

 

 

스택에만 있는 데이터: 복사

 

정수형과 같이 컴파일 타임에 결정되는 크기의 타입들은 스택에 모두 저장되므로,

실제 값의 복사가 빠르게 진행 될 수 있다.

 

Rust 에서는 스택에 저장할 수 있는 타입에 대해 달 수 있는 Copy trait 이 있다.

그래서, 어떤 타입이 Copy trait 을 갖고 있다면, 대입 과정 후에도 변수를 계속 사용 할 수 있다.

 

그러나, 이 중 Drop trait 을 구현하는 것이 있다면, Copy trait 을 어노테이션 할 수 없게끔 한다. 

 

Copy 가 가능한 타입은 아래와 같다.

  1. 모든 정수형 타입들
  2. bool
  3. 모든 부동소수점 타입
  4. 위 타입으로 구성된 튜플, (튜플 구성 에서 String 이 끼어있는 경우 불가)

 

[4. 소유권과 함수]

 

함수에게 변수를 넘기는 것 역시 값을 이동하거나 복사하게 된다.

 

값의 반환 역시 소유권을 이동 시킨다.

 

 

 

 

 

[99. 보일러 플레이트 코드]

'Rust' 카테고리의 다른 글

슬라이스  (0) 2022.08.18
참조자와 빌림  (0) 2022.08.18
함수와 제어문  (0) 2022.08.17
Rust 변수  (0) 2022.08.08
Rust project 생성  (0) 2022.08.08