C.W.K.
Stream
Lesson 02 of 05 · published

Deref & Drop

~10 min · smart-pointers, deref, drop, coercion

Level 0Rust 호기심러
0 XP0/80 lessons0/19 achievements
0/100 XP to next level100 XP to go0% complete

Box<String>String 메서드를 부르거나, &str 을 원하는 데 &String 을 넘길 수 있는 이유가 뭐야? 답은 Deref trait — 스마트 포인터를 투명하게 느끼게 하는 메커니즘이야.

Deref: 가리키는 것처럼 행동하기

Deref 구현은 *pointer 가 안쪽 값으로의 참조를 반환하게 하고 — 더 중요하게는 — deref coercion 을 가능하게 해: 컴파일러가 메서드나 함수가 안쪽 타입을 기대하는 곳마다 &Box<T>&T 로, &String&str 로 자동 변환해. 그게 Box<String> 이 String 으로 '그냥 되는' 이유야.

실전의 deref coercion

Borrowing 트랙부터 이름 없이 이걸 기대왔어: &my_string&str 파라미터에 넘기는 게 되는 건 Stringstr 로 deref 하니까. 컴파일러가 필요한 만큼 deref coercion 을 체이닝해서, &Box<String> 가 두 단계 거쳐 보이지 않게 &str 파라미터에 닿아.

Deref 가 스마트 포인터를 투명하게 만들어. Box, Rc 같은 게 Deref 를 구현하니까, 걔들 통해 안쪽 값의 메서드를 직접 불러. 스마트 포인터가 능력 (힙 저장, 참조 카운팅) 을 더하면서 값을 쓰려고 계속 unwrap 하게 안 만들어.

Drop, 동반자

Ownership 트랙에서 Drop 을 만났어 — 스코프 끝에 도는 정리. 스마트 포인터가 거기 기대: Box 가 drop 되면 힙 할당을 해제하고; Rc 가 drop 되면 카운트를 내리고 0 에서만 해제해. DerefDrop 이 함께 스마트 포인터가 뒤에서 자원을 관리하면서 값처럼 행동하게 만들어.

Code

투명한 접근을 위해 Deref 구현하기·rust
use std::ops::Deref;

struct MyBox<T>(T);

impl<T> MyBox<T> {
    fn new(x: T) -> MyBox<T> { MyBox(x) }
}
impl<T> Deref for MyBox<T> {
    type Target = T;
    fn deref(&self) -> &T { &self.0 } // 이제 *my_box 가 안쪽 값에 닿음
}

fn hello(name: &str) { println!("Hello, {name}!"); }

fn main() {
    let b = MyBox::new(String::from("Ferris"));
    // deref coercion: &MyBox<String> -> &String -> &str, 자동으로
    hello(&b);
    println!("{}", *b); // 명시적 deref
}

External links

Exercise

Deref 가진 MyBox<T> 튜플 struct 를 구현해. &str 받는 함수를 쓰고 &MyBox<String> 으로 불러 — deref coercion 이 너 대신 MyBox<String> -> String -> str 를 체이닝하는 걸 확인해. 그다음 Deref impl 을 빼고 호출이 컴파일 안 되는 걸 봐. Deref 가 뭘 벌어줬어?
Hint
Deref 없으면 &MyBox<String> 은 그냥 불투명한 래퍼야 — &str 로 자동 변환 없음. Deref 구현이 컴파일러가 래퍼를 꿰뚫어 안쪽 값을 보게 해주는 거야.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.