나만의 공부 노트

스마트 포인터 본문

Rust

스마트 포인터

va95 2025. 1. 28. 01:28

Box<T>

 

박스는 스택 대신 힙에 데이터를 저장한다는 점 외에는, 성능적인 오버헤드가 없습니다. 하지만 여러 가지의 추가 기능 또한 가지고 있지 않습니다. 여러분은 이를 아래와 같은 상황에서 가장 자주 쓰게 될 것입니다:

  • 컴파일 타임에 크기를 알 수 없는 타입을 갖고 있고, 정확한 사이즈를 알 필요가 있는 맥락 안에서 해당 타입의 값을 이용하고 싶을 때
  • 커다란 데이터를 가지고 있고 소유권을 옮기고 싶지만 그렇게 했을 때 데이터가 복사되지 않을 것이라고 보장하기를 원할 때
  • 어떤 값을 소유하고 이 값의 구체화된 타입을 알고 있기보다는 특정 트레잇을 구현한 타입이라는 점만 신경 쓰고 싶을 때

역참조 강제가 가변성과 상호작용 하는 법

불변 참조자에 대한 *를 오버 라이딩하기 위해 Deref 트레잇을 이용하는 방법과 비슷하게, 러스트는 가변 참조자에 대한 *를 오버 라이딩하기 위한 DerefMut 트레잇을 제공합니다.

러스트는 다음의 세 가지 경우에 해당하는 타입과 트레잇 구현을 찾았을 때 역참조 강제를 수행합니다:

  • T: Deref<Target=U>일때 &T에서 &U로
  • T: DerefMut<Target=U>일때 &mut T에서 &mut U로
  • T: Deref<Target=U>일때 &mut T에서 &U로

std::mem::drop을 이용하여 값을 일찍 버리기

fn main() {
    let c = CustomSmartPointer { data: String::from("some data") };
    println!("CustomSmartPointer created.");
    drop(c);
    println!("CustomSmartPointer dropped before the end of main.");
}

drop(c)를 통해 소유권을 넘김으로써, 미리 .drop()이 호출되는 효


Rc<T>, 참조 카운팅 스마트 포인터

  • Rc<T>가 오직 단일 스레드 시나리오 상에서만 사용 가능하다는 점을 주의
  • Rc::clone을 호출하는 매번마다, 해당 Rc<List>가 가지고 있는 데이터에 대한 참조 카운트는 증가할 것이고, 그 데이터는 참조자가 0개가 되지 않으면 메모리 정리되지 않을 것입니다

RefCell<T>

참조자와 Box<T>를 이용할 때, 빌림 규칙의 불변성은 컴파일 타임에 집행됩니다. RefCell<T>를 이용할 때, 이 불변성은 런타임에 집행됩니다. 참조자를 가지고서 여러분이 이 규칙을 어기면 컴파일러 에러를 얻게 될 것입니다. RefCell<T>를 가지고서 여러분이 이 규칙을 어기면, 여러분의 프로그램은 panic!을 일으키고 종료될 것입니다.

 

RefCell<T>는 런타임에 빌림을 추적합니다

불변 및 가변 참조자를 만들때, 우리는 각각 &  &mut 문법을 사용합니다. RefCell<T>을 이용할때는 borrow와 borrow_mut 메소드를 사용하는데, 이들은 RefCell<T>가 소유한 안전한 API 중 일부입니다. borrow 메소드는 스마트 포인터 타입인 Ref<T>를 반환하고, borrow_mut는 스마트 포인터 타입 RefMut<T>을 반환합니다. 두 타입 모두 Deref를 구현하였으므로 우리는 이들을 보통의 참조자처럼 다룰 수 있습니다.


Rc<T>와 RefCell<T>를 조합하여 가변 데이터의 복수 소유자 만들기

RefCell<T>를 사용하는 일반적인 방법은 Rc<T>와 함께 조합하는 것입니다. Rc<T>이 어떤 데이터에 대해 복수의 소유자를 허용하지만, 그 데이터에 대한 불변 접근만 제공하는 것을 상기하세요. 만일 우리가 RefCell<T>을 들고 있는 Rc<T>를 갖는다면, 우리가 변경 가능하면서 복수의 소유자를 갖는 값을 가질 수 있습니다!

 


참조 순환 방지하기: Rc<T>를 Weak<T>로 바꾸기

Rc::downgrade를 호출하고 여기에 Rc<T>에 대한 참조자를 넘겨서 Rc<T> 인스턴스 내의 값을 가리키는 약한 참조 (weak reference) 를 만들 수 있습니다. 여러분이 Rc::downgrade를 호출하면, 여러분은 Weak<T> 타입의 스마트 포인터를 얻게 됩니다.

Weak<T>가 참조하고 있는 값이 이미 버려졌을지도 모르기 때문에, Weak<T>가 가리키고 있는 값을 가지고 어떤 일을 하기 위해서는 그 값이 여전히 존재하는지를 반드시 확인해야 합니다. 이를 위해 Weak<T> upgrade 메소드를 호출하는데, 이 메소드는 Option<Rc<T>>를 반환할 것입니다.

 

'Rust' 카테고리의 다른 글

쓰레드  (0) 2025.01.28
클로저  (0) 2025.01.27
라이프타임  (0) 2025.01.23
모듈  (0) 2025.01.23
Tutorial  (0) 2025.01.23