Rust - Concept of Smart Pointers
Rust - Concept of Smart Pointers
Smart Pointers
• Rust allocates everything on the stack by default.
• You can store things on the heap by wrapping them in smart pointers
like Box.
• Pointers are basically variables that store the address of another
variable.
• Smart pointers are data types that behave like a traditional pointer
with additional capabilities such as automatic memory management
or bounds checking.
• Smart pointers implement traits
fn main() {
let stack_data = 20; //The value stack_data is stored in a heap
let hp_data = Box::new(stack_data); // points to the data in the heap
println!("hp_data = {}", hp_data); // output will be 20.
}
how to use a box to store an i32 value on
the heap.
fn main() {
let var_i32 = 5;
//stack
let b = Box::new(var_i32);
//heap
println!("b = {}", b);
}
• In order to access a value pointed by a variable, use dereferencing. The * is used as a
dereference operator. Below is how we use dereference with Box.
fn main() {
let x = 5;
//value type variable
let y = Box::new(x);
//y points to a new value 5 in the heap
println!("{}",5==x);
println!("{}",5==*y);
//dereferencing y
}
fn main() {
let x = Box::new(5);
let y = x.clone();
println!("x = {}, y = {}", x, y);
}
/*
Op => x = 5, y = 5
*/
Rc<T
>
• Rust supports reference counting with Rc.
• Rc” is a kind of smart pointer that is used to share ownership of immutable data across different
parts of a program within the same thread.
• It keeps track of how many references exist to a particular value, allowing multiple parts of the
code to access it concurrently.
• It also deallocates the memory when the last reference goes out of scope.
use std::rc::Rc;
fn main(){
let data = Rc::new(42);
let reference1 = Rc::clone(&data);
let reference2 = Rc::clone(&data);
println!("Data: {}", data);
}
Rc
use std::rc::Rc;
fn main() {
let data = Rc::new(vec![1, 2, 3]);
let data1 = data.clone();
let data2 = data.clone();
println!("data: {:?}", data);
println!("data1: {:?}", data1);
println!("data2: {:?}", data2);
}
RefCell
• RefCell<T> is another type that enables interior mutability, but it works for non-
Copy types.
• It allows multiple immutable borrows or one mutable borrow.
• If the borrowing rules are violated, RefCell<T> will panic at runtime.
use std::cell::RefCell;
fn main() {
let x = RefCell::new(vec![1, 2, 3]);
let y = &x;
let z = &x;
x.borrow_mut().push(4);
y.borrow_mut().push(5);
z.borrow_mut().push(6);
println!("x: {:?}", x.borrow());
}
use std::rc::Rc;
use std::cell::RefCell;
#[derive(Debug)]
struct Node {
value: i32,
next: Option<Rc<RefCell<Node>>>, // Use Rc for shared ownership and RefCell for mutability
}
fn main() {
// Create nodes using Rc and RefCell
[II. B.TECH CSE] [RUST PROGRAMMING LAB MANUAL] PAGE NO:46
let first = Rc::new(RefCell::new(Node {
value: 1,
next: None,
}));
let second = Rc::new(RefCell::new(Node {
value: 2,
next: None,
}));
let third = Rc::new(RefCell::new(Node {
value: 3,
next: None,
}));
// Link the nodes to form the list
first.borrow_mut().next = Some(second.clone());
second.borrow_mut().next = Some(third.clone());
// Traverse and print the linked list
let mut current = Some(first.clone());
println!("Linked List:");
while let Some(node) = current {
println!("{}", node.borrow().value);
current = node.borrow().next.clone(); // Move to the next node
}
}