Inflearn brand logo image

인프런 커뮤니티 질문&답변

정수한님의 프로필 이미지
정수한

작성한 질문수

우아한 고성능 프로그래밍 언어 Rust 입문 및 활용

소유권을 넘기지 않고 빌려주기 | 임대

&r1 을 써야하는지 r1을 써야하는지?

작성

·

67

1

fn main() {

let mut s = String::from("헬로");

let r1 = &s;

let r2 = &s;

println!("r1 = {}, r2= {}", r1, r2);

}

여기서 println! 부분에 r1을 사용하건 &r1을 사용하건 둘다 "헬로" 로 같은 값이 나옵니다.

엄밀하게 말하면 r1은 문자열s의 주소값일 것 같아서 질문 드립니다.

그리고 주소값을 바탕으로 실제 값을 가져오는 건 일반적으로 &연산자가 아닌 *연산자를 사용하지 않는지요?

답변 1

0

김대현님의 프로필 이미지
김대현
지식공유자


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

    let r1: &String = &s;
    let r2: &&String = &r1;
    let r3: &&&String = &&&s;

    println!("r1 = {}, r2= {}, r3 = {}", r1, r2, r3);
}

수강 및 좋은 질문 감사합니다.


우선, println!("{}", v)에서 어떤 값이 출력됐다고 해서, 그 값이 그대로 보인 게 아니라는 점을 명확히 하면 좋겠습니다.

질문에 적어주신대로, r1은 s의 주소값, 러스트 용어로 말하자면 참조값인 게 맞습니다. 둘의 타입이 명백히 다르죠. s의 타입은 String이고, r1의 타입은 &String입니다.

단지, println!매크로에 활용되는 std::fmt::Display 트레이트 구현과 러스트의 deref 규칙 때문에 화면에는 "헬로"라는 문자열이 잘 보인 것 뿐입니다.

강의에 따로 다룬 내용이 아니므로 자세히 설명드리기는 어렵습니다만, 간단하게 적자면, println!에 {}자리에 찍을 대상들은 Display::fmt 메소드를 호출하게 되어있고, 참조값인 경우 원형(참조를 해제해서)의 fmt까지 쫓아가서 출력할 수 있는 기능이 있습니다.

따라서 몇 중으로 참조한 참조값이든 원래 타입의 값이 Display할 수 있는 값이라면 같은 내용이 화면에 보이는 것입니다.

질문에 적어주신, r1을 써야하느냐, &r1을 써야 하느냐는 질문에는, 상황에 따라 다를 수 있지만, 일반적으로 이미 r1이 참조값이므로, 그걸 또 참조할 일은 흔치는 않겠다고 말씀드리겠습니다. (하지만 C/C++같은 언어에서 때로 이중포인터를 쓰기도 하니, 비슷한 용례로 쓰일 수도 있겠죠)

더 궁금하신 내용이 있으시면 편히 말씀주세요 

정수한님의 프로필 이미지
정수한

작성한 질문수

질문하기