当前位置:网站首页>[rust notes] 11 practical features
[rust notes] 11 practical features
2022-07-03 08:36:00 【phial03】
11 - Practical features
Special type | brief introduction |
---|---|
Drop | Deconstruction function . When clearing the value Rust Automatic clearing code |
Sized | Mark the special type , For the type of size you can know at compile time ( Instead of dynamically sized types like slices ) |
Clone | For types that support clone values |
Copy | Mark the special type , For types that can be cloned simply by copying the values contained in memory byte by byte |
Deref And DerefMut | Special type of smart pointer type |
Default | Reasonable for “ The default value is ” The type of |
AsRef And AsMut | Convert the special type , Borrow some kind of reference |
Borrow And BorrowMut | Convert the special type , similar AsRef And AsMut , But the additional guarantee of consistent hashing 、 Order and equal |
From And Into | Convert the special type , Convert a value of one type to another |
ToOwned | Convert the special type , Convert references to all values |
11.1-Drop
When the owner of a value leaves ,Rust It will automatically clear (Drop) This value . Clearing values involves releasing related values 、 Heap space , And the system resources owned by this value .
Rust Standard special type
std::ops::Drop
:trait Drop { fn drop(&mut self); }
Clearance can occur under various conditions , Including variables out of scope 、 The value of the expression is
;
Operators discard 、 When truncating a vector, delete its elements from the end , wait .Designed for custom types
Drop
:- Structure and special design
struct Appellation { name: String, nicknames: Vec<String> } trait Drop { fn drop(&mut self); } impl Drop for Appellation { fn drop(&mut self) { print!("Dropping {}", self.name); if !self.nicknames.is_empty() { print!(" (AKA {})", self.nicknames.join(", ")); } println!(""); } }
- Test code :
fn main() { let mut a = Appellation { name: "Zeus".to_string(), nicknames: vec!["cloud collector".to_string, "king of the gods".to_string()] }; println!("before assignment"); a.drop(); a = Appellation { // After the second assignment , The first assignment is cleared name: "Hera".to_string(), nicknames:vec![] }; println!("at end of block"); a.drop(); } // a Out of scope , The second assignment is cleared
- Results output
before assignment Dropping Zeus (AKA cloud collector, king of the gods) at end of block Dropping Hera
If the value of the variable is transferred to another place , Causes the variable to be uninitialized when it is out of scope ,Rust The variable will not be cleared , Because this variable has no value to clear . here ,Rust Will use an invisible flag to track the status of variables , This flag indicates whether the value of the variable needs to be cleared :
let p; { let q = Appellation { name: "Cardamine hirsuta".to_string(), nicknames: vec!["shotweed".to_string(), "bittercress".to_string()] }; if complicated_condition() { p = q; } } // q The scope of ends here println!("Sproing!"); // p The scope of ends here
If a type implements
Drop
Special type , Can no longer be achievedCopy
Special type .- If a type contains
Copy
Special type , Then a simple byte to byte assignment will produce an independent copy of the value . - Call the same... Multiple times in the same data
drop
The method is wrong .
- If a type contains
The standard front-end module contains a function to clear the value :
fn drop<T>(_x: T) { }
- Receive the value of a parameter , Take ownership from the caller , Then do nothing .
- Rust When out of scope , eliminate
_x
Value , Just like clearing the values of other variables .
11.2-Sized
Fixed size types (sized type): Its value has the same size in memory .
- Every
u64
Occupy 8 Bytes . - Every
(f32, f32, f32)
Tuple proportion 12 Bytes . - For enumeration types , Its value always takes up the space that can save its largest variation .
Vec<T>
Have a variable size buffer allocated on the heap , howeverVec
The value itself contains a pointer to the buffer 、 Buffer capacity and its length . thereforeVec<T>
It is also a fixed size type .
- Every
Non fixed size type (unsized type): The size of its value in memory is not fixed . Such as
str
and[T]
Type represents a collection of values of uncertain size , So they are non fixed size .- String slice type
str
( Note that there is no&
) It is non fixed size . Literal of a string"diminutive"
and"big"
It's right 19 and 3 bytestr
References to slices . - Such as
[T]
( Again, there is no&
) Such array slice types are also non fixed size , Shared references&[u8]
Can point to any size[u8]
section .
- String slice type
The reference to the special target is also a non fixed size type .
- A feature target is a pointer to a value that implements a given feature . Such as
&str::io::Write
andBox<std::io::Write>
All point to the implementationWrite
Pointer to a value of a special type . - The reference target may be a file 、 A network socket , Or it does
Write
The custom type of . - Because of the realization of
Write
The type of is extensible , allWrite
As a type, it is considered to be non fixed size , That is, the size of its value is variable .
- A feature target is a pointer to a value that implements a given feature . Such as
The last field of the structure may be of non fixed size . here , The structure itself is also of non fixed size .
Rc<T>
The reference count pointer is internally implemented as a pointer to a private typeRcBox<T>
The pointer to , This type is used to save the typeT
And its reference count .struct RcBox<T: Sized> { ref_count: usize, value: T, // }
value
The value of the field isT
, Save itRc<T>
Reference count of .Rc<T>
Dereference is a pointer to this field .ref_count
Field saves the reference count .
Pointers to non fixed size values are fat pointers , Two words wide .
- Fat pointers contain both pointers to slices , It also includes the length of the slice .
- The special target also contains a pointer to the virtual table implemented by the method .
All fixed size types are implemented
std::marker::Sized
Special type , This feature has no method or association type .- Rust This feature is automatically implemented for all types it applies .
- Developers cannot implement it by themselves .
Application scenarios : Bind type variables .
T: Sized
binding , requirementT
It must be a type of known size at compile time .- This type is called marked type (marker trait), Some types can be marked as having characteristics of interest .
Most generic variables are by default Rust Limited to the use of
Sized
type .struct S<T> {...}
Will be Rust Understood as astruct S<T: Sized> {...}
.- If the developer writes
struct S<T: ?Sized> {b: Box<T>}
( Its meaning is “ Is not necessarilySized
”), that Rust Will allow the use ofS<str>
andS<Write>
, Defined as fat pointer ; It's also allowed to useS<i32>
andS<String>
, Defined as a normal pointer .
I don't know whether to fix the size (questionably sized): Type variables have
?Sized
binding , This makes this type possibleSized
, Maybe not .
11.3-Clone
std::clone::Clone
Special type : Applicable to types that can copy themselves .trait Clone: Sized { fn clone(&self) -> Self; fn clone_from(&mut self, source: &Self) { // take self It is amended as follows source A copy of . *self = source.clone() } }
Rust Do not automatically clone values , Instead, it requires an explicit call to a method :
- Cloning a value usually involves creating a copy of everything the value has and allocating memory , therefore
clone
No matter in time consumption or memory consumption , May be more expensive . - Such as clone
Vec<String>
It's not just about copying vectors , Also copy all that it containsSring
Elements . Rc<T>
andArc<T>
Such a reference count pointer is an exception , Cloning them intelligently simply increments the corresponding reference count , Then return the new pointer .
- Cloning a value usually involves creating a copy of everything the value has and allocating memory , therefore
Yes
Clone
Examples of special types : Many meaningful types of replication operations , It's all doneClone
.- The original type
bool
andi32
; - Container type
String
、Vec<T>
andHashMap
;
- The original type
nothing
Clone
Examples of special types : Some types do not make sense to implement replication .std::sync::Mutex
;std::fs::File
Replication fails when the operating system has no necessary resources . But it provides atry_clone
Method , This method returns an error reportstd::io::Result<File>
.
Cloning must be foolproof .
11.4-Copy
Assignment will transfer the value , Instead of copying values . Transferring values is more conducive to tracking the resources owned by variables .
A simple type that does not own any resources can be
Copy
type , This type of assignment produces a copy of the value , Instead of transferring values and making the original variable uninitialized .If the type implements
std::marker::Copy
Mark the special type , So it's going to beCopy
type .trait Copy: Clone { }
It is also very simple to implement custom types :
impl Copy for MyType { }
Realization
Copy
The type of must comply with the rules :- Rust Only allow types to be implemented when byte to byte deep replication meets the requirements
Copy
. - Those who may have any resources , For example, the type of heap buffer or operating system hook , Can't achieve
Copy
. - Any implementation
Drop
The type of special type cannot beCopy
. If a type requires special cleanup code , Then you must need special copy code , So it can't beCopy
type .
- Rust Only allow types to be implemented when byte to byte deep replication meets the requirements
Special type derivation :
#[derive(Copy)]
Let the type deriveCopy
;#[derive(Clone, Copy)]
Let types derive at the same timeClone
andCopy
.
11.5-Deref
And DerefMut
std::ops::Deref
Andstd::ops::DerefMut
The special type can modify the dereference operator*
and.
Behavior on custom types .Box<T>
andRc<T>
Such a pointer type implements these two special types . If there is aBox<Complex>
Type valueb
, that*b
The quote isb
Point toComplex
Value , andb.re
It refers to the actual number of parts .- Context assignment , And borrowing modifiable references from reference targets , Then you can use
DerefMut
( Variable dereference ) Special type . Deref
Only get read-only permission .
Definition of special type :
trait Deref { type Target: ?Sized; fn deref(&self) -> &Self::Target; } trait DerefMut: Deref { fn deref_mut(&mut self) -> &mut Self::Target; }
deref
andderef_mut
Method reception&Self
Quote and return&Self::Target
quote .Target
yesSelf
contain 、 Owned or referenced resources . aboutBox<Complex>
Come on ,Target
The type ofComplex
.DerefMut
yesDeref
An extension of : If you can dereference and modify resources , Then you can borrow a shared reference to it .- The references returned by these two methods have the same as
&self
The same long life span , thereforeself
It will always be borrowed during the life of the returned reference .
Dereference forced transformation (deref coercion): One type is “ mandatory ” Show another type of behavior . Such as the implementation
DerefMut
You can realize the type conversion of modifiable references .- about
Rc<String>
Valuer
, If you want to call itString::find
, Then you can simply writer.find('?')
. here&Rc<String>
Be coerced into&String
, becauseRc<T>
RealizedDeref<Target=T>
. - Can be in
String
UseSplit_at
Other methods , Even ifSplit_at
yesStr
Slice type method , becauseString
RealizedDeref<Target=str>
. here&String
Forced transition to&str
. - If byte vector
v
, Pass it an expected byte slice&[u8]
Function of , Then you can put&v
As a parameter , becauseVec<T>
RealizedDeref<Target=[T]>
. - Rust Will not try to dereference forced transformation to meet the type variable binding .
- about
11.6-Default
All types with default values are implemented
std::default::Default
Special type :trait Default { fn default() -> Self; }
String
YesDefault
The implementation of is as follows :impl Default for String { fn default() -> String { String::new() } }
Default
It can represent a large number of parameter sets ( Most parameters usually do not need to be changed ) The default value generated by the structure of .If type
T
RealizedDefault
, Then the standard library will automatically beRc<T>
、Arc<T>
、Box<T>
、Cell<T>
、RefCell<T>
、Cow<T>
、Mutex<T>
andRwLock<T>
RealizationDefault
.- If all element types of tuple type are implemented
Default
, And the tuple type also implementsDefault
, Then this tuple will hold the default value of each element by default . - If all fields of the structure are implemented
Default
, You can use#[derive(Default)]
Automatically implement for the structureDefault
. - whatever
Option<T>
The default values of areNone
.
- If all element types of tuple type are implemented
11.7-AsRef
And AsMut
If a type implements AsRef<T>
, Then you can borrow one from it &T
. namely AsRef
Is a shared reference , Again AsMut
That is, modifiable references .
trait AsRef<T: ?Sized> {
fn as_ref(&self) -> &T;
}
trait AsMut<T: ?Sized> {
fn as_mut(&mut self) -> &mut T;
}
11.8-Borrow
And BorrowMut
If a type implements
Borrow<T>
, So it'sborrow
Methods can effectively borrow one from themselves&T
. differAsRef
: Only when&T
When it has the same hash and comparison characteristics as the value it borrows , A type can be implementedBorrow<T>
.trait Borrow<Borrowed: ?Sized> { fn borrow(&self) -> &Borrowed; }
Application scenarios :
- It is often used to deal with keys in hash tables or trees .
- Handle values that will be hashed or compared for other reasons .
String
RealizedAsRef<str>
、AsRef<u8>
andAsRef<Path>
, But these three target types usually have different hash values . Only&str
Slicing ensures correspondence OfString
Have the same hash result , thereforeString
onlyBorrow<str>
.
11.9-From
And Into
std::convert::From
andstd::convert::Into
Special type represents type conversion , That is, consume a type of value , Then return another type of value .AsRef
andAsMut
A special type is a reference borrowed from one type to another ;From
andInto
Is to take ownership of their parameters , Conversion type , Then return the ownership of the result to the caller .
// The definitions of these two types are symmetrical trait Into<T>: Sized { fn into(self) -> T; } trait From<T>: Sized { fn from(T) -> Self; }
Each type in the standard library
T
It's all doneFrom<T>
andInto<T>
Special type .Use
Into
You can make it more flexible to receive parameters :use std::net::Ipv4Addr; fn ping<A>(address: A) -> std::io::Result<bool> where A: Into<Ipv4Addr> { let ipv4_address = address.into(); ... }
ping
Function can receiveIpv4Addr
As a parameter , You can also receiveu32
or[u8; 4]
Array of .u32
and[u8; 4]
Arrays of have been implementedInto<Ipv4Addr>
Special type .Call the above feature :
println!("{:?}", ping(Ipv4Addr::new(23, 21, 68, 141))); // Pass in Ipv4Addr println!("{:?}", ping([66, 146, 219, 98])); // Pass in [u8; 4] println!("{:?}", ping(0xd076eb94_u32)); // Pass in u32
From
onlyFrom<[u8; 4]>
andFrom<u32>
:let addr1 = Ipv4Addr::from([66, 146, 219, 98]); let addr2 = Ipv4Addr::from(0xd076eb94_u32);
In the process of conversion, the resources of the original value can be used to build the converted value .
let text = "Beautiful Soup".to_string(); let bytes: Vec<u8> = text.into();
11.10-ToOwned
Clone
Achieved the cloning of the reference target ;ToOwned
Then it realizes the cloning of referencing itself . It can convert references to values of all types :trait ToOwned { type Owned: Borrow<Self>; fn to_owned(&self) -> Self::Owned; // It can be returned and borrowed as &Self Any type of }
It can be downloaded from
Vec<T>
Borrow a&[T]
, therefore[T]
Can achieveToOwned<Owned=Vec<T>>
.str
RealizedToOwned<Owned=String>
;Path
RealizedToOwned<Owned=PathBuf>
;
11.11-Borrow
And ToOwned
example
Whether a function should receive parameters by reference or by value , In some cases, it is more appropriate to decide whether to borrow or acquire ownership when the program is running . In response to this problem ,
std::borrow::Cow
It can realize write time cloning (clone on write):enum Cow<'a, B: ?Sized + 'a> where B: ToOwned { Borrowed(&'a B), Owned(<B as ToOwned>::Owned), }
Cow<B>
You can borrow rightB
A shared reference to ;- You can also have a value , Then borrow such a reference .
Cow
Use of : Returns statically allocated string constants or computed strings .Convert an error enumeration into a message : Most variants can be handled with fixed size strings , But some also need to include additional data in the message . I can return one
Cow<'static, str>
:use std::path::PathBuf; use std::borrow::Cow; fn describe(error: &Error) -> Cow<'static, str> { match *error { Error::OutOfMemory => "out of memory".into(), Error::StackOverflow => "stack overflow".into(), Error::MachineOnFire => "machine on fire".into(), Error::Unfathomable => "machine bewildered".into(), Error::FileNotFound(ref path) => { format!("file not found: {}", path.display()).into() } } }
describe
If the caller of does not need to modify the return value , You can putCow
Think of it as a&str
:println!("Disaster has struck: {}", describe(&error));
When you need a caller of all types , It can also be easily obtained :
let mut log: Vec<String> = Vec::new(); ... log.push(describe(&error).into_owned());
Cow
You can putdescirbe
And its caller can postpone memory allocation until necessary .
See 《Rust Programming 》( Jim - Brandy 、 Jason, - By orendov , Translated by lisongfeng ) Chapter 13
Original address
边栏推荐
猜你喜欢
Get to know unity2 for the first time
OpenGL learning notes
[MySQL] MySQL Performance Optimization Practice: introduction of database lock and index search principle
UE4 source code reading_ Mobile synchronization
Some understandings of 3dfiles
UE4 source code reading_ Bone model and animation system_ Animation process
P1596 [USACO10OCT]Lake Counting S
Solution détaillée de toutes les formules de fonction de transfert (fonction d'activation) du réseau neuronal MATLAB
梯度下降法求解BP神经网络的简单Demo
MXone Pro自适应2.0影视模板西瓜视频主题苹果cmsV10模板
随机推荐
796 · unlock
【Rust 笔记】09-特型与泛型
[concurrent programming] consistency hash
Osgearth starry background
Visual Studio (VS) shortcut keys
Graphics_ Games101/202 learning notes
了解小程序的笔记 2022/7/3
C#课程设计之学生教务管理系统
Campus lost and found platform based on SSM, source code, database script, project import and operation video tutorial, Thesis Writing Tutorial
producer consumer problem
【Rust 笔记】10-操作符重载
UE4 source code reading_ Bone model and animation system_ Animation node
Unity Editor Extension - drag and drop
【Rust笔记】05-错误处理
Markdown directory generation
Osgearth topographic shading map drawing
使用base64编码传图片
简易入手《SOM神经网络》的本质与原理
[linear table] basic operation of bidirectional linked list specify node exchange
MySQL 8