[Rust] Box<T> (Smart Pointer)

고승우·2023년 7월 27일
0

Rust

목록 보기
1/16
post-thumbnail

Smart Pointer

rust에서는 일반적으로 &symbol을 사용하여 pointer의 종류인 reference를 사용한다. 일반 포인터는 자료를 대여하는 것만 가능한 것에대 반해 smart pointer는 그것을 소유할 수 있으며, 대부분 그렇게 작동한다. StringVec<T>도 스마트 포인터에 해당된다. Smart pointer는 추가적인 metadata와 capabilities를 가지고 있다. Vec, String, Box<T> 등이 해당된다.

Struct std::boxed::Box

pub struct Box<T, A = Global>(_, _)
where
         A: Allocator,
         T: ?Sized;

T타입에 대해 heap allocation을 가지는 스마트 pointer type이다. Box는 값을 동적 할당하고, 해당 값이 스코프를 벗어난 경우 자동으로 할당을 해제한다. Rust는 stack에 데이터를 저장할 때 해당 데이터의 사이즈를 알 수 없으면, 컴파일에러가 난다. trait object나 recursive struct type을 활용할 때 이런 문제가 생길 수 있다.

  • 컴파일 시간에 그 크기를 알 수 없는 자료형을 사용하며 그 자료형의 값의 정확한 크기가 필요할 때
  • 큰 자료를 사용하며 그것을 복제하지 않고 소유권을 이전하고자 할 때
  • 특정 자료형의 값이 아니라 특정 trait을 구현하는 자료형의 값을 소유하고자 할 때
    사용할 수 있다. 또한 따로 Box<T>에서 꺼내는 작업 없이 사용할 수 있다. 그리고 소유권을 가진 일반 변수가 그렇듯이 범위를 벗어나면 메모리가 해제된다.

Example

Recursive Type

recursive type은 compile time에 그 크기를 알 수 없다. recursive type은 자신과 같은 자료형의 값을 참조하기 때문에 이론적으로 무한히 커질 수 있다. 보편적인 재귀 자료형으로는 ConsList(construction list)가 있다. Cons enum의 첫 번째 값은 리스트에 사용할 data type, 두 번째 값은 List enum을 저장하도록 하지만, 이 값에 List enum을 그대로 넣으면 컴파일러는 크기가 무한해질 수 있음을 인지하고 컴파일을 거부한다. 이를 Box<T>로 해결할 수 있다.

enum List {
    Cons(i32, Box<List>),
    Nil,
}

use crate::List::{Cons, Nil};

fn main() {
    let list = Cons(1,
        Box::new(Cons(2,
            Box::new(Cons(3,
                Box::new(Nil)
            ))
      ))
    );
}
profile
٩( ᐛ )و 

0개의 댓글