Rust pointers: Difference between revisions
(→Weak) |
|||
(3 intermediate revisions by the same user not shown) | |||
Line 81: | Line 81: | ||
This behaves similarly to <code>Box</code> in that it returns a pointer with an overridden dereference operator, but it also ensures that as long as one reference still exists to an object, it won't get <code>drop()</code> called on it. | This behaves similarly to <code>Box</code> in that it returns a pointer with an overridden dereference operator, but it also ensures that as long as one reference still exists to an object, it won't get <code>drop()</code> called on it. | ||
{{ NOTE | | |||
the rust docs make a strong argument that because of ownership semantics,<br> | |||
a parent should own children, and not the other way around. | |||
}} | |||
<syntaxhighlight lang="rust"> | <syntaxhighlight lang="rust"> | ||
use std::rc::Rc; | use std::rc::Rc; | ||
Line 86: | Line 90: | ||
#[derive(Debug)] | #[derive(Debug)] | ||
enum Node { | enum Node { | ||
Children(Vec<Rc<Node>>), | |||
Leaf, | |||
} | } | ||
fn main() { | fn main() { | ||
let | let b1 = Node::Leaf; | ||
let | let b2 = Node::Leaf; | ||
Rc::clone(& | let a = Node::Children(vec![ | ||
Rc::clone(&b1), | |||
Rc::clone(&b2), | |||
Rc::clone(& | |||
]); | ]); | ||
dbg!(&b1); | dbg!(&b1); | ||
Line 103: | Line 106: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
</blockquote><!-- Rc<T> --> | </blockquote><!-- Rc<T> --> | ||
== Weak<T> == | |||
<blockquote> | |||
<code>Weak<T></code> is a companion to <code>Rc<T></code>.<br> | |||
It allows you to downgrade an Rc reference so that the Weak reference does not impact the deletion of the object.<br> | |||
The example given in the docs is that a node could have a weak reference to it's parent. | |||
See https://doc.rust-lang.org/stable/book/ch15-06-reference-cycles.html | |||
</blockquote><!-- Weak<T> --> | |||
== Arc<T> == | |||
<blockquote> | |||
Behaves like <code>Rc<T></code>, but is threadsafe. | |||
</blockquote><!-- Arc<T> --> | |||
== RefCell<T> == | == RefCell<T> == |
Latest revision as of 04:57, 10 February 2023
Documentation
custom smart pointers https://doc.rust-lang.org/stable/book/ch15-02-deref.html
Pointers/References
let foo = String::new("hi"); &foo // `&` get reference to foo let ref = &foo; *ref // `*` de-reference to get foo instance
Smart Pointers
The standard library implements some reusable smart-pointers to handle edge-cases.
Libraries may implment their own smart-pointers (and so can you).Pointer Relevant Traits
Box<T>
Box types let you represent recursive types, where the total size is unknown at compile time,
by replacing your type with a pointer to it.The docs use the example of a recursive enum.
An Enum's size is determined by it's largest possible value.
If an enum refers to an instance of itself the compiler is unable to determine it's size.The box type allocates your object to the heap, and returns a pointer to it.
Pointers have a known size, so you can assign that instead.
Also, it implements the Deref trait, which allows you to use box as if it were a reference to the object you assigned to it.#[derive(Debug)] enum Path { Dir(String, Box<Path>), File(String), } impl Path { fn file(file: &str) -> Box<Path> { Box::new( Path::File(file.to_string()) ) } fn dir(dir: &str, path: Box<Path>) -> Box<Path> { Box::new( Path::Dir(dir.to_string(), path) ) } } fn main() { let mypath = Path::dir("/var", Path::dir("/tmp", Path::file("/foo.txt"))); dbg!(mypath); }Rc<T>
The
Rc
(Reference Counting) smart-pointer lets you have an object with multiple owners.
This is useful for graphs, where a node may have multiple parents.This behaves similarly to
Box
in that it returns a pointer with an overridden dereference operator, but it also ensures that as long as one reference still exists to an object, it won't getdrop()
called on it.NOTE:
the rust docs make a strong argument that because of ownership semantics,
a parent should own children, and not the other way around.use std::rc::Rc; #[derive(Debug)] enum Node { Children(Vec<Rc<Node>>), Leaf, } fn main() { let b1 = Node::Leaf; let b2 = Node::Leaf; let a = Node::Children(vec![ Rc::clone(&b1), Rc::clone(&b2), ]); dbg!(&b1); dbg!(&b2); }Weak<T>
Weak<T>
is a companion toRc<T>
.
It allows you to downgrade an Rc reference so that the Weak reference does not impact the deletion of the object.
The example given in the docs is that a node could have a weak reference to it's parent.See https://doc.rust-lang.org/stable/book/ch15-06-reference-cycles.html
Arc<T>
Behaves like
Rc<T>
, but is threadsafe.RefCell<T>
This wraps an object with a single parent, but allows a mutable reference while immutable references exist.
See https://doc.rust-lang.org/stable/book/ch15-05-interior-mutability.html