Rust Chapter 24 Smart Pointer
Implementation of smart pointers
Smart pointers are usually implemented using struct.
And implement the two traits of Deref and Drop
Deref trait: Allows instances of smart pointer struct to be used like references
Drop triat: Allows you to customize the code when the smart pointer instance goes out of scope
Common smart pointers in the standard library
Box<T>:existheapAllocate values on memory Rc<T>: Reference technology types that enable multiple ownership Ref<T> RefMut<T> passRefCall<T> access:exist运行时而不是编译时强制借用规则的类型
Use Box to point to data on Heap
He is the simplest smart pointer
let b = Box::new(5); println!("b = {}",b);
rust needs to know the size of space occupied by a type when compiling
However, the size of the recursive type cannot be confirmed at compile time
Using Box can solve it. Box is a pointer and size confirmation
Deref Trait
Deref dereference, we can customize the behavior of dereference operator*
With Deref, smart pointers can be processed like regular references
Dereference operator
let x = 5; let y = &x; assert_eq!(5,x); assert_eq!(5,*y);
Using box
let y = Box::new(5); assert_eq!(5,*y);
Customize a tuple pointer
struct Mypointer<T>(T); //Structure tuple, only one member// Tuple structure is equivalent to a structure without member names, accessed through indeximpl<T> Mypointer<T> { fn new(x : T) -> Mypointer<T> { Mypointer(x) } } //To make it a pointer, the Deref method needs to be implementedimpl<T> Deref for Mypointer<T> { type Target = T; fn deref(&self) -> &T { &self.0 } } let y = Mypointer::new(5); assert_eq!(5,*y);
Deref implicit dereference method
When the incoming type does not match the function receiving type, if the parameter implements the Deref trait, the compiler will automatically call the Deref method to match the parameter type;
example:
fn hello(name : & str) { println!("hello,{}",name); } hello("Rust"); let m = Mypointer::new(String::from("Rust")); //The original type is &mypointer<String> // deref &string // deref &str hello(&m);
Drop Trait
After implementation, you can customize the actions that occur when the value leaves the scope.
Required to implement drop method
When the variable leaves the scope, the drop method is automatically called
example:
impl<T> Drop for Mypointer<T> { fn drop(&mut self) { println!("run drop function----") } }
Cannot call the .drop() method manually
However, you can call the drop (variable) function to manually log out
Rc reference count smart pointer
Sometimes, a value has multiple owners
To support multiple ownership, Rc is introduced
Rc can only be used in single-threaded scenarios
method:
Rc::clone(&a) function: Increase the reference count
Rc::strong_count(&a): Get the reference count
example:
enum Node2 { Next2(i32 ,Rc<Node2> ), Nul } use self::Node2::Next2; use self::Node2::Nul; .... main..... let a = Rc::new( Next2(5, Rc::new( Nul ) )); println!("a value is {}",Rc::strong_count(&a)); let b = Rc::new( Next2( 12, Rc::clone(&a) ) ); println!("after b :a value is {}",Rc::strong_count(&a)); let c = Rc::new( Next2( 11, Rc::clone(&a) ) ); println!("after c: a value is {}",Rc::strong_count(&a)); { let d = Rc::new( Next2( 15, Rc::clone(&a) ) ); println!("after d :a value is {}",Rc::strong_count(&a)); } println!("end : a value is {}",Rc::strong_count(&a)); ....end....
With immutable references, you can share read-only data between different parts of the program
Compared with clone(), it is a shallow copy and has a fast execution speed.
RefCell and internal variability
Internal variability:
Allows modification of data while holding only immutable references
RefCell Checks Ownership Rules at Runtime
Only used for single threaded code
Box | Rc | RefCell | |
---|---|---|---|
Same data owner | one | Multiple | one |
Variability, borrowing check | Variable, immutable borrowing (compilation-time check) | Immutable borrowing (compile-time check) | Variable, immutable borrowing (runtime check) |
Under normal circumstances, an immutable variable borrow cannot be borrowed.
let a = 10; let b = &mut a;//mistake
Refcall's .borrow_mut() method: Modify the value of an immutable reference
This is all about this article about Rust smart pointer. For more related Rust smart pointer content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!