This week I had a nice discussion on Smart Pointer versus RUST. My takeaways are the following.
Feature | C++ Smart Pointers | Rust Ownership & Borrowing (also has SmartPointer) |
---|
Goal | Manage dynamic memory with RAII – “Resource Acquisition Is Initialization” | Ensure memory safety at compile time |
Core Concept | Pointer with automatic resource release | Ownership rules enforced by the compiler |
Memory Safety | Runtime safety via smart pointers | Compile-time safety via borrow checker |
And while programming
Concept | C++ | Rust |
---|---|---|
Unique ownership | std::unique_ptr<T> | Box<T> (heap allocation) + ownership transfer |
Shared ownership | std::shared_ptr<T> | Rc<T> (single-threaded), Arc<T> (thread-safe) |
Non-owning reference | Raw pointer or std::weak_ptr<T> | &T (immutable borrow), &mut T (mutable borrow) |
Null safety | nullptr possible | No null references (Option<T> is used instead) |
Code example:
#include <memory>
std::unique_ptr<int> makeInt() {
return std::make_unique<int>(42);
}
int main() {
std::unique_ptr<int> ptr = makeInt();
// *ptr = 10; // OK
}
fn make_int() -> Box<i32> {
Box::new(42)
}
fn main() {
let ptr = make_int();
// *ptr = 10; // OK
}
Same ease of use
Safety considerations
Category | C++ | Rust |
---|
Dangling pointers | Possible if raw pointers or misused shared_ptr | Prevented by ownership rules |
Use-after-free | Possible, unless smart pointers are carefully used | Statistically eliminated by borrow checker |
Data races | Possible in multithreaded contexts | Compiler prevents them via aliasing rules |
Reference counting | Runtime cost with shared_ptr /weak_ptr | Runtime cost with Rc /Arc , compile-time borrow checks otherwise |
Zero-cost abstraction | Not guaranteed | Strong focus on zero-cost abstractions |
Reference Cycles
But also consider this nice chapter in the RUST handbook: Reference Cycles Can Leak Memory – The Rust Programming Language
Even though Rust enforces strict memory safety at compile time, reference cycles are still possible when using reference-counted types like Rc<T>
or Arc<T>
—similar to shared_ptr
in C++. This is one of the few scenarios in which Rust can leak memory, albeit safely (i.e., without undefined behavior).
Concept | C++ | Rust |
---|---|---|
Reference cycles | Can occur with std::shared_ptr | Can occur with Rc<T> or Arc<T> |
Prevention | Use std::weak_ptr to break cycles | Use Weak<T> to break cycles |
Memory leak risk | Yes, if cycles are not broken | Yes, in same cases — logic errors, not unsafe |
Runtime check? | No automatic detection | No automatic detection eitherEven though Rust enforces strict memory safety at compile time, reference cycles are still possible when using reference-counted types like Rc<T> or Arc<T> —similar to shared_ptr in C++. This is one of the few scenarios in which Rust can leak memory, albeit safely (i.e., without undefined behavior).Concept C++ Rust Reference cycles Can occur with std::shared_ptr Can occur with Rc<T> or Arc<T> Prevention Use std::weak_ptr to break cyclesUse Weak<T> to break cyclesMemory leak risk Yes, if cycles are not broken Yes, in same cases — logic errors, not unsafe Runtime check? No automatic detection No automatic detection either |