Smart Pointer
rust에선 까다로운 규칙을 컴파일 타임에 강요를 하는데, 그것들 회피하고 유연한 프로그램을 만들 수 있게 해준다.
- 관련 Trait
- Deref: 역참조를 할 수 있도록 해준다. ex) &String -> &str
- Drop: 메모리 해제될 때, 실행될 코드를 지정할 수 있다.
Box
값을 힙에 할당하게 해준다. 그래서 미리 데이터 크기를 알 수 없어서 스택에 못 올리는 데이터를 힙에 저장할 수 있다. ex) 순환 참조 enum
- Use Case
- 컴파일 타임에 크기를 알 수 없는 타입이 있는데, 정확한 크기를 요구할 때
- ex) 순환 참조 enum
- enum은 varient 중에 가장 큰 것을 기준으로 메모리를 할당하기 때문
- ex) 순환 참조 enum
- 커다란 데이터의 소유권을 옮기고 싶지만, 그때 데이터 복사를 피하고 싶을 때
- 어떤 값을 소유하고 이 값이 구체화된 타입보다는 특정 트레이트를 구현한 타입이라는 점만 신경 쓰고 싶을 때
- 컴파일 타임에 크기를 알 수 없는 타입이 있는데, 정확한 크기를 요구할 때
fn main() {
let b = Box::new(5);
println!("b = {}", b);
}
Rc
Reference counting 복수의 소유권을 가능하게 해줌
- Rc::clone을 통해서 reference count에 +1를 수행 후, 소유권을 받는다.
- reference count가 0이 되면 메모리를 정리한다.
enum List {
Cons(i32, Rc<List>),
Nil,
}
use crate::List::{Cons, Nil};
use std::rc::Rc;
fn main() {
let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
let b = Cons(3, Rc::clone(&a));
let c = Cons(4, Rc::clone(&a));
}
Week
- Rc
에는 순환 참조 문제가 존재한다. (순환 참조를 통해 reference count가 0이 안 되는 문제) - 이때 Rc::downgrade(&data)를 통해서 Week 객체를 받을 수 있다.
- 이것은 Week 객체는 존재해도 메모리를 정리 당할 수 있다.
week.upgrade(): Option<Rc>를 반환한다.
RefCell
데이터에 대한 불변 참조자가 있을 때라도 데이터를 변경할 수 있게 해준다. (규칙을 어기면 runtime에서 panic을 일으킨다.)
.borrow():Ref<T>를 반환.borrow_mut():RefMut<T>를 반환RefCell<T>는 활성화된 스마트 포인터(Ref,RefMut)들이 몇개나 있는지 추적해서 규칙을 벗어났을 때 panic을 일으킨다.
impl Messenger for MockMessenger {
fn send(&self, message: &str) {
let mut one_borrow = self.sent_messages.borrow_mut();
let mut two_borrow = self.sent_messages.borrow_mut(); // panic!
one_borrow.push(String::from(message));
two_borrow.push(String::from(message));
}
}