Rust 공식 문서를 참고한 글입니다.
변수를 바인딩해 복사가 아닌 이동을 하는 경우에는 소유권이 이전되어 접근할 수 없다. 함수에서 반환된 이후에도 그 값을 사용하고 싶다면, 반환값으로 전달해서 소유권을 다시 이전하는 방법도 있다. Rust는 참조(Reference)를 통해 소유권을 가져가는 것이 아니라, 대여할 수 있도록 한다.
1. 참조 Reference
참조란 포인터와 유사하게 해당 주소에 저장되어 있는 데이터에 접근해 읽어올 수 있다. 이때, 소유권은 넘어가지 않는다. 따라서 함수를 호출한 이후에도 해당 변수를 계속해서 사용할 수 있다. 참조할 때는 매개변수 자료형 앞에 & 를 붙여서 소유권을 가진 변수가 그 범위를 벗어나도 drop 함수를 호출하지 않는다.
예제를 살펴보자.
fn main() {
let s1 = String::from("hello");
let len = calculate_length(&s1);
println!("The length of '{s1}' is {len}.");
}
fn calculate_length(s: &String) -> usize {
s.len()
}
s1에 hello라는 string이 할당되어 있고, len에 calculate_length(&s1)의 반환값을 할당하고 있다. 이때, s1 앞에 &를 붙여 참조를 나타낸다. 만약에 &를 지우면 println!에서 s1를 사용할 수 없다는 오류가 발생할 것이다.
가변 참조 Mutual Reference
일반적으로 참조한 변수는 불변성을 띄기 때문에 수정할 수 없다. 이때 수정을 하려면 &과 mut을 같이 사용하면 된다. 이를 가변 참조라고 하는데, 원본 변수 자체도 가변성을 띄어야 한다.
fn main() {
let mut s = String::from("hello");
change(&mut s);
}
fn change(some_string: &mut String) {
some_string.push_str(", world");
}
가변 참조를 할 때 주의할 점은 가변 참조를 사용하는 동안에는 해당 값에 하나의 참조만 있어야 한다는 점이다. 아래 코드처럼 r1과 r2가 동시에 s에 대해 가변 참조하면 오류가 발생한다.
let mut s = String::from("hello");
let r1 = &mut s;
let r2 = &mut s;
println!("{}, {}", r1, r2);
이러한 제약은 같은 변수가 가변 참조로 인해 서로 다르게 수정하면서 발생하는 데이터 레이스를 방지한다. 데이터 레이스 이슈는 둘 이상의 가변 참조 뿐만 아니라, 가변 참조와 불변 참조를 섞어 사용할 때도 발생한다. 가변 참조를 통해 불변 참조로 참조하는 값을 변경하는 경우, 의도치 않은 결과가 발생할 수 있다. 이러한 상황에 대비해 Rust는 컴파일 시점에서 오류를 발생시킨다.
데이터 레이스는 아래와 같은 조건에서 발생한다.
- 두 개 이상의 포인터가 동시에 같은 데이터에 접근하는 경우
- 적어도 하나의 포인터가 데이터를 쓰기 위한 용도로 사용되는 경우
- 데이터에 대한 접근을 동기화하는 메커니즘이 없는 경우
Dangling Reference
포인터를 사용하는 언어는 메모리를 해제하면서 그 메모리를 포인터로 가리키면 Dangling Pointer를 만들 수 있다. 이는 다른 변수가 할당된 메모리를 잘못 참조하는 오류다. 그러나 Rust는 컴파일러가 이러한 오류를 방지한다.
예제를 살펴보자.
fn main() {
let reference_to_nothing = dangle();
}
fn dangle() -> &String {
let s = String::from("hello");
&s
}
이 코드는 컴파일 에러가 발생한다. 생명주기에 대한 오류가 발생하는데, 이는 함수에서 참조한 값을 반환하는데 이미 소멸된 값이기 때문이다. s는 dangle()에서 선언되고 함수가 끝나면 s는 소멸된다. 근데 소멸된 String에 대한 참조를 반환하기 때문에 오류가 발생한다. 발생하지 않게 하려면, 참조가 아닌 String 자체를 반환해야 한다.
'언어 > Rust' 카테고리의 다른 글
[Rust] 5-1. 구조체 사용 (0) | 2024.10.09 |
---|---|
[Rust] 4-3. Slice Type (0) | 2024.09.28 |
[Rust] 4-1. 소유권(Ownership) (0) | 2024.09.28 |
[Rust] 3-3. 제어문(Control Flow) (0) | 2024.09.26 |
[Rust] 3-2. 함수와 주석 (0) | 2024.09.25 |