Rust, 쉽게 하자!

Rust 입문

[Rust] Box

바로크냥 2022. 10. 15. 01:45

2. Box

스마트 포인터는 데이터의 실제 내용은 heap에 있고 그 주소를 가리키는 포인터를 비롯한 헤더는 stack에 있어서 스코프에 따른 소유권 규칙을 지킵니다.

Box는 정확히 이런 특징을 가지고 있는 가장 기본적인 스마트 포인터입니다. 

heap에 저장되는 구조체를 하나 만들고 Box에 넣어  특징을 살펴보겠습니다.

fn main(){
   // 1
   let mut point1 = Box::new(Point { x: 1, y: 1});
   println!("{:?}", point1);
   let mut point2 = point1;    // 재할당
   println!("{:?}", point1);
}

// Point 구조체 선언
#[derive(Debug)]
pub struct Point {
    pub x: i32,
    pub y: i32,
}

// 출력
..에러
70 |     let mut point1 = Box::new(Point { x: 1, y: 1});
   |         ---------- move occurs because `point1` has type `Box<Point>`, which does not implement the `Copy` trait
71 |     println!("{:?}", point1);
72 |     let mut point2 = point1;
   |                      ------ value moved here
73 |     println!("{:?}", point1);
   |                      ^^^^^^ value borrowed here after move
   |

// 1: Box<Point> 타입 변수 point1을 만들었습니다.

heap에 데이터를 저장한다는 것을 강조하기 위해 구조체를 만들었지만 사실 숫자형이나 문자열 리터럴을 Box에 넣어도 그 값들은 heap에 저장됩니다.

// 출력: String에서 발생했던 에러가 똑같이 발생했습니다.

Box<Point>가 Copy 트레이트를 구현하지 않았다는 에러 메시지도 동일합니다.

재할당될 때 소유권의 이동이 발생하고 point1은 가지고 있던 값을 잃고 삭제됩니다.

 

만약 재할당할 때 Box<Point> 타입인 point1을 할당하지 않고 point1의 역참조를 할당하면 어떻게 될까요?

다음 코드를 보겠습니다.

 let mut point1 = Box::new(Point { x: 1, y: 1});
 println!("{:?}", point1);  
 let mut point2 = *point1;     // 1
 println!("{:?}", point2);

// 출력
Point { x: 1, y: 1 }
Point { x: 1, y: 1 }

// 1: point1의 역참조를 할당했습니다.

역참조를 하면 포인터가 가리키는 주소에 있는 데이터를 지칭하는 것입니다. 

 

사실 point2의 출력은 point1을 할당하는 것이나 역참조인 *point1을 할당하는 것이나 똑같습니다.

다만 데이터 타입이 다릅니다.

point1을 할당받으면 Box<Point> 타입이 되고  *point1을 할당받으면 point 타입이 됩니다.

역참조를 하면 그 내용물을 Boix 밖으로 끄집어내게 됩니다. 

 

 
반응형

'Rust 입문' 카테고리의 다른 글

[Rust] Rc와 Weak  (0) 2022.10.21
[Rust] Vec  (0) 2022.10.19
[Rust] 스마트 포인터  (1) 2022.10.15
[Rust] crate.io  (0) 2022.10.13
[Rust] 알아 두면 도움되는 standard trait (2/2)  (0) 2022.10.13