728x90
Chapter 15 - Smart Pointer
- 포인터 : 메모리에 주소를 포함하는 변수에 대한 일반적인 개념. (참조, 가리킴)
- 스마트 포인터 : 포인터처럼 작동하지만 추가 메타데이터와 기능도 있는 데이터 구조.
- 자신이 가리키는 데이터를 소유한다.
- 특성:
- Deref : 스마트 포인터 구조체의 인스턴스가 참조처럼 동작하여, 참조 또는 스마트 포인터로 작업하도록 코드 작성 가능
- Drop : 스마트 포인터의 인스턴스가 범위를 벗어날 때 실행되는 코드를 사용자 지정할 수 있다.
- 일반적으로 구조체를 사용하여 구현
Box
Box<T>
:
- 스택에 남는 것은 힙 데이터에 대한 포인터이다.
- 사용 :
- 컴파일 시점에 크기를 알 수 없는 유형이 있고 정확한 크기가 필요한 컨텍스트에서 해당 유형의 값을 사용
- 대량의 데이터가 있고 소유권을 이전하려고 하지만 이전 시 데이터가 복사되지 않도록 보장
- 특정 유형이 아닌 특정 특성을 구현하는 유형인지만 중요시하고 값을 소유하고자 하는 경우
fn main() {
let b = Box::new(5);
println!("b = {b}");
}
상자를 활용한 재귀적 유형
- 재귀는 이론적으로 무한히 계속될 수 있으므로 Rust는 값에 필요한 공간을 알 수 없다.
- 상자는 알려진 크기를 가지므로 재귀적 유형 정의에 상자를 삽입하여 재귀적 유형을 활성화할 수 있다.
- 링크드 리스트
enum List { Cons(i32, List), //현재 항목과 다음 항목 Nil, //다음 항목 없이 호출된 값만 포함 }
Deref
- 역참조 연산자\
- Trait구현을 통한 참조처리
struct MyBox<T>(T); impl<T> MyBox<T> { fn new(x: T) -> MyBox<T> { MyBox(x) } } use std::ops::Deref; impl<T> Deref for MyBox<T> { type Target = T; fn deref(&self) -> &Self::Target { &self.0 //무한하지 않게함 } } fn main() { let x = 5; let y =MyBox::new(x); assert_eq!(5, x); assert_eq!(5, *y); }
Deref 강제 변환
Deref Mutability
- From &T to &U when T : Deref<Target=U>
- From &mut T to &mut U when T : DerefMut<Target=U>
- From &mut T to &U when T: Deref<Target=U>
Drop
- 모든 유형에서 특성에 대한 구현을 제공할 수 있으며, 해당 코드는 파일이나 네트워크 연결과 같은 리소스를 해제하는 데 사용할 수 있다.
- Box가 드롭되면 상자가 가리키는 힙의 공간을 할당 해제한다.
값 조기 정리
std::mem::drop
을 사용하면 객체를 조기 정리할 수 있다.
- Rust는 범위를 활용하여 자동으로 메모리 해제를 진행하지만 해당 메서드를 통해 수동으로 진행할 수 있다.
Rc
→ 참조 카운트 스마트 포인터
enum List {
Cons(i32, Box<List>),
Nil,
}
use crate::List::{Cons, Nil};
fn main() {
let a = Cons(5, Box::new(Cons(10, Box::new(Nil))));
let b = Cons(3, Box::new(a));
let c = Cons(4, Box::new(a)); //해당 코드에서는 a의 소유권이 b로 넘어갔기 때문에
} //c에서 받을 a의 소유권이 없어서 에러가 발생함
-------------------
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)); //그러나 Rc를 사용한 clone에서는 복사이기때문에 가능
}
- Rc::clone은 깊은 복사가 아니기 때문이다.
- Rc::clone은 참조 카운트를 늘린다.
RefCell
- 내부 가변성 패턴은 Rust의 디자인 패턴이다.
- Rc와 다르게 단일 소유권을 보유한다.
- 주로 멀티 스레드에서 사용함.
Box VS Rc VS RefCell
- Rc : 하나의 데이타에 다중 소유권이 가능하다; 그 외 불가능.
- Box : 가변, 불변 참조 모두 컴파일 가능하다.; Rc 불변참조, RefCell 가변 불변을 런타임에서 확인한다.
- RefCell : 불변일때도 런타임에서는 가변할 수 있게한다. (내부 가변적)
- Rc::downgrade → Weak
- weak_count는 0일 필요 없어 삭제될 수 있다.
728x90
'Languages > RUST' 카테고리의 다른 글
[RUST] TRPL : Chapter 13 - Iterators & Closures (0) | 2024.12.02 |
---|---|
[RUST] TRPL : Chapter 12 - I/O Project (0) | 2024.12.01 |
[RUST] TRPL : Chapter 11 - Test (0) | 2024.12.01 |
[RUST] TRPL : Chapter 10 - Generic Types & Lifetime (0) | 2024.11.29 |
[RUST] TRPL : Chapter9 - Error Handling (0) | 2024.11.29 |