Smart Pointers di Rust
Smart pointer adalah struct yang bertindak seperti pointer tapi punya metadata & kemampuan tambahan. Mereka memungkinkan pola ownership yang tidak bisa diekspresikan dengan reference biasa.
Box<T> — Heap Allocation
Box<T> menyimpan data di heap, dengan pointer di stack. Berguna untuk:
- Tipe dengan ukuran tidak diketahui saat compile time (recursive types)
- Data besar yang tidak ingin di-copy saat transfer ownership
- Trait objects (
Box<dyn Trait>)
let b = Box::new(5);
println!("{}", b); // 5
// Recursive type — tanpa Box, Rust tidak tahu ukuran List
enum List {
Cons(i32, Box<List>),
Nil,
}
use List::{Cons, Nil};
let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
Rc<T> — Reference Counting (Single-Threaded)
Rc<T> (Reference Counted) memungkinkan banyak owner untuk data yang sama — menghitung jumlah reference dan men-drop data saat count 0.
use std::rc::Rc;
let a = Rc::new(String::from("halo"));
let b = Rc::clone(&a); // +1 ref count (bukan deep clone!)
let c = Rc::clone(&a);
println!("count: {}", Rc::strong_count(&a)); // 3
Catatan: Rc<T> tidak thread-safe. Data yang di-share hanya bisa dibaca (immutable).
Arc<T> — Atomic Reference Count (Multi-Threaded)
use std::sync::Arc;
use std::thread;
let data = Arc::new(vec![1, 2, 3]);
let mut handles = vec![];
for i in 0..3 {
let data = Arc::clone(&data);
handles.push(thread::spawn(move || {
println!("Thread {}: {:?}", i, data);
}));
}
for h in handles { h.join().unwrap(); }
Arc sama seperti Rc tapi pakai atomic operations — aman untuk thread.
RefCell<T> — Interior Mutability
RefCell<T> memindahkan aturan borrow checker dari compile time ke runtime. Kamu bisa mendapatkan &mut bahkan saat RefCell itu sendiri immutable.
use std::cell::RefCell;
let c = RefCell::new(5);
*c.borrow_mut() += 10;
println!("{}", c.borrow()); // 15
Hati-hati: kalau aturan borrow dilanggar saat runtime, program panic!
Rc<RefCell<T>> — Shared Mutable State
use std::rc::Rc;
use std::cell::RefCell;
let data = Rc::new(RefCell::new(vec![1, 2, 3]));
let ref1 = Rc::clone(&data);
let ref2 = Rc::clone(&data);
ref1.borrow_mut().push(4);
ref2.borrow_mut().push(5);
println!("{:?}", data.borrow()); // [1, 2, 3, 4, 5]
Decision Matrix
| Kebutuhan | Pakai |
|---|---|
| Data heap, single owner | Box<T> |
| Banyak owner, single-thread, immutable | Rc<T> |
| Banyak owner, multi-thread, immutable | Arc<T> |
| Interior mutability, single-thread | RefCell<T> |
| Shared mutable, single-thread | Rc<RefCell<T>> |
| Shared mutable, multi-thread | Arc<Mutex<T>> |