brunch

You can make anything
by writing

C.S.Lewis

by 유윤식 Jul 14. 2024

Rust : 참조 & 역참조

#Ref #DeRef

맨날 아리송하게 기억하는 참조 & 역참조


간단하게 String 을 활용해서 참조 & 역참조를 비교해보자.



fn main() {

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

    let s2 = s1;  // s1의 소유권이 s2로 이동

    // println!("{}", s1);  // 오류: s1은 이미 이동!

    

    let s3 = String::from("world");

    let len = calculate_length(&s3);  // s3를 빌려줌

    println!("'{}의 길이: {}", s3, len);  // s3는 여전히 사용 가능 -> 5


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

    change(&mut s4);  // 가변 참조로 빌려줌

    println!("s4: {}", s4); / -> hello, world!

}


fn calculate_length(s: &String) -> usize {  // 불변 참조

    s.len()

}


fn change(s: &mut String) {  // 가변 참조

    s.push_str(", world"); // 자동 역참조 발생에 따라 * 기호가 필요없다.

}



위 코드에서 change 함수를 파악해보면,

s.push_str 을 호출하면서 가변 참조로 가져온 s 변수는 자동 역참조가 일어난다.

즉, *s 를 이용한 명시적 역참조를 할 필요가 없다.


그렇다면, 어떤 경우에 명시적 역참조를 구현할까?

간단하게 .push_str 함수를 사용하지 않고 내가 직접 s 변수를 조작하려고 한다면

명시적 역참조를 사용해야 한다.



fn change(s: &mut String) {  // 가변 참조

    // s.push_str(", world"); // 자동 역참조 발생에 따라 * 기호가 필요없다.

    *s = String::from("Hello, world");

    // 또는

    *s += ", world";

}


어떤 차이가 있는지 명확히 보인다.


이게 Vec 을 사용하든 HashMap 을 사용하든 대동소이하게 적용된다.

소유권 개념을 이해하려면 해당 개념도 명확하게 이해하고 있어야 안전하게 다음 스텝으로 넘어갈 수 있다.


혹시 struct 와 trait 을 이용해 impl 을 구현한 객체를 사용할 때에도

해당 함수를 호출함으로서 Rust 는 자동 역참조를 일으킨다.


끝.

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari