Rust에서는 다양한 종류의 포인터를 제공합니다. 이 포인터들은 메모리 안전성, 소유권, 뮤터불리티 등 다양한 측면에서 사용됩니다. 아래에 주요 포인터 타입에 대한 설명을 제공하겠습니다.
Rust에서는 여러 종류의 포인터를 제공합니다. 각각의 포인터는 메모리 안전성을 보장하는 데 다양한 방법을 사용합니다. 아래 테이블에서 주요 포인터 타입의 특징을 비교하겠습니다.
먼저 들어가기 전에 뮤터블과 (Mutable)과 이뮤터블(Immutable)의 간략히 짚고 갑니다. 아래는 비교한 표입니다.
뜻 | 변경 가능한 | 변경 불가능한 |
변수 선언 | let mut x = 5; | let x = 5; |
값 변경 | 가능 (x = 6;) | 불가능 |
배열/벡터 수정 | 가능 (vec.push(1);) | 불가능 |
메모리 안정성 | 상대적으로 낮음 | 높음 |
데이터 경쟁 조건 | 발생 가능성 있음 | 발생 가능성 없음 |
Rust에서의 중요성 | 소유권 모델에서 주의 필요 | 소유권 모델에서 안전 |
이 표는 뮤터블과 이뮤터블의 기본적인 차이와 Rust에서의 의미를 간략하게 비교하고 있습니다. Rust의 소유권 모델에서는 이 두 개념이 중요한 역할을 하며, 이를 통해 메모리 안정성과 병렬 프로그래밍의 안정성이 향상됩니다.
&T와 &mut T (참조와 뮤터블 참조)
- &T: 이뮤터블 참조, 즉 읽기 전용 참조입니다. 이 참조를 통해 데이터를 수정할 수 없습니다.
- &mut T: 뮤터블 참조로, 이 참조를 통해 데이터를 수정할 수 있습니다.
Box<T>
- Box<T>: 힙에 데이터를 저장합니다. Box는 단일 소유자를 가지며, 데이터의 크기가 컴파일 타임에 알려져 있어야 합니다.
Rc<T>와 Arc<T> (참조 카운팅 포인터)
- Rc<T>: "Reference Counted"의 약자로, 단일 스레드 환경에서 여러 소유자를 가질 수 있습니다.
- Arc<T>: "Atomic Reference Counted"의 약자로, 멀티 스레드 환경에서 안전하게 사용할 수 있습니다.
RefCell<T>
- RefCell<T>: 런타임에 뮤터불리티를 변경할 수 있게 해주는 포인터입니다. 컴파일 타임에 뮤터불리티를 검사할 수 없는 경우에 유용합니다.
Unsafe<T>
- *const T와 *mut T: 이것은 "원시 포인터"라고도 하며, Rust의 안전성 보장을 우회합니다. 주로 FFI (외부 함수 인터페이스)나 시스템 호출에서 사용됩니다.
각각의 포인터 타입은 특정 목적과 상황에 따라 설계되었습니다. 예를 들어, Box<T>는 힙 할당을 필요로 하는 큰 데이터 구조나 소유권을 명확히 해야 하는 경우에 사용됩니다. Rc<T>와 Arc<T>는 여러 곳에서 읽기 전용으로 접근해야 하는 데이터에 사용됩니다. RefCell<T>은 런타임에 뮤터불리티가 변경될 수 있는 상황에서 사용됩니다. 원시 포인터는 극단적인 최적화나 시스템 수준의 프로그래밍이 필요할 때 사용됩니다.
위 내용을 표로 다시 정리한 부분입니다.
&T | Immutable | 없음 | 높음 | 데이터 읽기 | 빠름, 안전함 | 수정 불가능 |
&mut T | Mutable | 없음 | 높음 | 데이터 수정 | 빠름, 안전함 | 하나의 뮤터블 참조만 허용됨 |
Box<T> | 선택적 | 있음 | 높음 | 힙 할당 | 소유권 명확, 안전함 | 힙 할당/해제 비용 발생 |
Rc<T> | Immutable | 있음 | 높음 | 여러 소유자 (단일 스레드) | 참조 카운팅으로 안전성 보장 | 뮤터불리티 없음, 오버헤드 있음 |
Arc<T> | Immutable | 있음 | 높음 | 여러 소유자 (멀티 스레드) | 멀티 스레드 안전 | 뮤터불리티 없음, 오버헤드 있음 |
RefCell<T> | 런타임 | 없음 | 중간 | 런타임 뮤터불리티 | 런타임에서 뮤터불리티 변경 가능 | 런타임 비용, 패닉 가능성 있음 |
Unsafe<T> | 선택적 | 있음 | 낮음 | FFI, 배열 접근 등 | 최적화 가능, 유연함 | 안전성 보장되지 않음 |
아래는 각각의 포인터들에 대한 예제입니다.
&T와 &mut T
let x = 5;
let y = &x; // 이뮤터블 참조
let z = &mut x; // 뮤터블 참조 (컴파일 에러, x가 뮤터블이 아님)
Box<T>
let x = Box::new(5);
Rc<T>와 Arc<T>
use std::rc::Rc;
let x = Rc::new(5);
let y = x.clone();
RefCell<T>
use std::cell::RefCell;
let x = RefCell::new(5);
*x.borrow_mut() += 1;
Unsafe<T>
let x: i32 = 42;
let r: *const i32 = &x;
unsafe { println!("r points to: {}", *r); }
Rust는 메모리 안전성과 다양한 요구 사항을 충족하기 위해 여러가지 포인터들이 있습니다. 이 포인트들의 사용법을 익히고 적절한 포인터 타입을 선택하는 것은 중요한 일입니다.
'Rust' 카테고리의 다른 글
Rust에서 정규 표현식 마스터하기 (0) | 2025.03.04 |
---|---|
[Rust] 함수 값 전달(Passing Arguments by Value) 완벽 가이드 (0) | 2025.02.24 |
[Rust] Option<T> 의 사용방법에 대하여 (2) | 2023.12.06 |
Rust in Jupyter notebook (0) | 2023.12.04 |
[Rust] Clap과 커맨드 라인 argument 다루기 (0) | 2023.09.07 |