#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 는 자동 역참조를 일으킨다.
끝.