본문 바로가기

Rust

[Rust] 참조자(References) 와 빌림(Borrowing)

참조자와 빌림에 대해 알아보겠습니다. 

참조자는 C, C++에서 포인터와 비슷하다고 생각하시면 이해하기 쉬울 것 같습니다.

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()
}

참조자는 &을 사용해 나타냅니다. 저번에 배웠던 소유권에 따르면 s1을 calculate_length에 전달한다면 소유권은 calculate_length로 넘어가고 println! 에서 s1에 대한 출력은 에러를 발생시킬 것입니다. 하지만 참조자(&)를 이용해 잠깐 

calculate_length가 s1을 사용할 수 있게 빌려주는 것입니다. 또한 함수의 파라미터로 참조자를 만드는 것을 "빌림"이라고 합니다.

 

만약 빌려간 객체의 수정을 하려 한다면 에러를 발생시킵니다.

fn main() {
    let s = String::from("hello");

    change(&s);
}

fn change(some_string: &String) {
    some_string.push_str(", world"); //에러 발생
}

 

만약 빌려간 객체를 수정하고 싶다고 한다면 가변 참조(Mutable References)를 사용해야 합니다.

 

fn main() {
    let mut s = String::from("hello");

    change(&mut s);
}

fn change(some_string: &mut String) {
    some_string.push_str(", world");
}

아까 위의 코드와 다른 점은 s의 선언에서 mut을 추가했다는 것과 change의 선언에서 파라미터로 &mut String을 받고 있는 것입니다.  이렇게 하면 빌린 객체의 수정이 가능하지만 여기에는 제약이 따릅니다.

특정한 스코프 내에 특정한 데이터 조각에 대한 가변 참조자를 딱 하나만 만들 수 있다.

 

let mut s = String::from("hello");

let r1 = &mut s;
let r2 = &mut s;

위의 코드처럼 같은 스코프 내에 가변 참조자를 2개를 만들려고 했기 때문에 에러가 발생합니다. 

이 문제는 새로운 스코프를 만들어 해결할 수 있습니다.

let mut s = String::from("hello");

{
    let r1 = &mut s;

} // 여기서 r1은 스코프 밖으로 벗어났으므로, 우리는 아무 문제 없이 새로운 참조자를 만들 수 있습니다.

let r2 = &mut s;

또한 불변 참조자를 가지고 있는 경우에도 가변 참조자를 만들지 못합니다.

let mut s = String::from("hello");

let r1 = &s; // 문제 없음
let r2 = &s; // 문제 없음
let r3 = &mut s; // 큰 문제

왜냐하면 불변 참조자는 데이터의 수정이 불가능하기 때문에 가변 참조자가 생성이 가능하다면 불변 참조자의 데이터가 변경될 수 있기 때문입니다.

 

'Rust' 카테고리의 다른 글

[Rust] enum 열거형  (0) 2022.04.23
[Rust] 구조체의 메소드  (0) 2022.04.22
[Rust] 소유권(Ownership)  (0) 2022.04.19
[Rust] 구조체  (0) 2022.04.18
[Rust] 데이터 타입  (0) 2022.04.16