欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

rust智能指針的具體使用

 更新時間:2023年12月07日 15:00:27   作者:int8  
智能指針是一些數(shù)據(jù)結(jié)構(gòu),它們的行為類似于指針但擁有額外的元數(shù)據(jù)和附加功能,本文就來介紹一下rust智能指針的具體使用,感興趣的可以了解一下

一、智能指針是什么

指針是一個存儲內(nèi)存地址的變量。這個地址指向一些其他數(shù)據(jù)。
智能指針是一類數(shù)據(jù)結(jié)構(gòu),它們類似指針,但是擁有額外的功能。智能指針的概念起源于C++。Rust標準庫提供了許多智能指針,比如String和Vec<T>,雖然我們并不這么稱呼它們,但這些類型都屬于智能指針。
智能指針通常使用結(jié)構(gòu)體實現(xiàn)。智能指針與常規(guī)結(jié)構(gòu)體的區(qū)別在于智能指針實現(xiàn)了Deref和Drop trait。Deref trait使智能指針表現(xiàn)的像引用一樣,這樣就可以編寫既用于引用、又用于智能指針的代碼。Drop trait允許我們自定義智能指針離開作用域時的行為。

在Rust中,引用和智能指針的一個區(qū)別是引用是一類只借用數(shù)據(jù)的指針;智能指針則擁有數(shù)據(jù)的所有權。

二、最常用的一些智能指針

1.Box<T>,用于在堆上分配
2.Rc<T>,一個引用計數(shù)類型,其數(shù)據(jù)可以有多個所有者
3.Ref<T> 和RefMut<T>,通過RefCell<T> 訪問(RefCell<T>是一個在運行時而不是在編譯時執(zhí)行借用規(guī)則的類型)

(一)Box指針

Box<T>類型是一個智能指針,因為它實現(xiàn)了Deref trait和Drop trait。
box把值放在堆上而不是棧上。留在棧上的則是指向堆數(shù)據(jù)的指針。除了數(shù)據(jù)被儲存在堆上而不是棧上之外,box沒有性能損失。不過也沒有很多額外的功能。
1.創(chuàng)建Box
使用new函數(shù)創(chuàng)建
例子

fn main() {
     let var_i32 = 5; // 默認數(shù)據(jù)保存在 棧 上
     let b = Box::new(var_i32); // 使用Box后數(shù)據(jù)會存儲在堆上
     println!("b = {}", b);
}

b離開作用域時,它將自動釋放。這個釋放包括b本身(位于棧上)和它所指向的數(shù)據(jù)(位于堆上)。

2.使用box
像使用引用一樣使用box。
使用解引用操作符 * 解引用box

fn main() {
     let x = 5; // 值類型數(shù)據(jù)
     let y = Box::new(x); // y是一個智能指針,指向堆上存儲的數(shù)據(jù)5
     println!("{}",5==x);
     println!("{}",5==*y); // 為了訪問y存儲的具體數(shù)據(jù),需要解引用
}
編譯運行結(jié)果如下
true
true
直接使用  5 == y  會返回false

3.使用Box創(chuàng)建遞歸類型
Rust需要在編譯時知道類型占用多少空間。一種無法在編譯時知道大小的類型是遞歸類型,其值的一部分可以是自身類型的另一個值。這種嵌套可以是無限的,所以Rust不知道遞歸類型需要多少空間。不過box有一個已知的大小,所以通過在遞歸類型定義中插入box,就可以創(chuàng)建遞歸類型了。一個常見遞歸類型就是鏈表。
實例

enum List {
     Cons(i32, List),
     Nil,
}
use crate::List::{Cons, Nil};
fn main() {
     let list = Cons(1, Cons(2, Cons(3, Nil)));//使用這個list來儲存1, 2, 3
}

第一個Cons儲存1和另一個List值。這個List是一個Cons值,此cons儲存2和下一個List值。這個list又是一個cons,儲存3和值為Nil的List。這段代碼編譯錯誤。因為這個類型 “有無限的大小”。
因為Box<T> 是一個指針,它的大小是確定的,所以將Box作為Cons的成員,這樣List的大小就確定了。

enum List {
     Cons(i32, Box<List>),
     Nil,
}
use crate::List::{Cons, Nil};
fn main() {
     let list = Cons(1,
         Box::new(Cons(2,
              Box::new(Cons(3,
                  Box::new(Nil))))));
}

三、兩個特性

(一)Deref Trait

1.Deref是由Rust標準庫提供的一個特性。
實現(xiàn)Deref之后就能把智能指針當作引用使用,相當于重載解引用運算符*。
Deref中包含deref()方法。
deref()方法用于引用self實例并返回一個指向內(nèi)部數(shù)據(jù)的指針。

例子

use std::ops::Deref;
struct DerefExample<T> {
     value: T
}
impl<T> Deref for DerefExample<T> {
     type Target = T;
     fn deref(&self) -> &Self::Target {
         &self.value
     }
}
let x = DerefExample { value: 'a' };
assert_eq!('a', *x);

范例

use std::ops::Deref;
struct MyBox<T>(T);
impl<T> MyBox<T> {
     fn new(x:T)-> MyBox<T> {
         MyBox(x)
     }
}
impl<T> Deref for MyBox<T> {
     type Target = T;
     fn deref(&self) -> &T {
         &self.0
     }
}
fn main() {
     let x = 5;
     let y = MyBox::new(x); // 調(diào)用new() 返回創(chuàng)建一個結(jié)構(gòu)體實例
     println!("5==x is {}",5==x);
     println!("5==*y is {}",5==*y); // 解引用y
     println!("x==*y is {}",x==*y); // 解引用y
}
編譯運行結(jié)果如下
5==x is true
5==*y is true
x==*y is true

每次使用 * 時, * 運算符都被替換成先調(diào)用deref方法再使用 * 解引用的操作,且只會發(fā)生一次,不會無限遞歸替換 * 操作符,解引用出i32類型的值就停止了

2.DerefMut trait用于重載可變引用的 * 運算符

3.Deref隱式轉(zhuǎn)換
Deref隱式轉(zhuǎn)換將實現(xiàn)了Deref的類型的引用轉(zhuǎn)換為另一種類型的引用。例如,將&String轉(zhuǎn)換為&str,因為String實現(xiàn)了Deref因此可以返回&str。Deref強制轉(zhuǎn)換是Rust在函數(shù)或方法傳參上的一種便利操作,并且只能作用于實現(xiàn)了Deref的類型。當這種特定類型的引用作為實參傳遞給和形參類型不同的函數(shù)時將自動轉(zhuǎn)換類型。這時會有一系列的deref方法被調(diào)用,把我們提供的類型轉(zhuǎn)換成了形參所需的類型。
Deref隱式轉(zhuǎn)換使Rust程序員在調(diào)用函數(shù)時無需使用過多& 和 *。這個功能方便我們編寫同時作用于引用或智能指針的代碼。

實例

//還是上面的MyBox<T>
fn hello(name: &str) {
     println!("Hello, {name}!");
}
let m = MyBox::new(String::from("Rust"));
hello(&m);

因為Deref隱式轉(zhuǎn)換,使用MyBox<String>的引用作為參數(shù)是可行的。
因為MyBox<T>實現(xiàn)了Deref,Rust可以通過deref將&MyBox<String>變?yōu)?amp;String。而String也實現(xiàn)了Deref,Rust再次調(diào)用deref將&String變?yōu)?amp;str,這就符合hello函數(shù)的定義了。

如果沒有Deref強制轉(zhuǎn)換,要把&MyBox<String>類型的值傳給hello函數(shù),則不得不編寫如下代碼

let m = MyBox::new(String::from("Rust"));
hello(&(*m)[..]);

(*m)MyBox<String>解引用為String,接著&和[..]將String轉(zhuǎn)換成&str。
沒有Deref強制轉(zhuǎn)換的話,所有這些符號混在一起將難以讀寫和理解。Deref強制轉(zhuǎn)換會自動執(zhí)行這些轉(zhuǎn)換。這些轉(zhuǎn)換發(fā)生在編譯時,所以沒有運行時損耗!

Deref隱式轉(zhuǎn)換有三種情形:
(1)當T實現(xiàn)Deref Target=U 時從 &T到 &U。
(2)當T實現(xiàn)DerefMut Target=U 時從 &mut T到 &mut U。
(3)當T實現(xiàn)Deref Target=U 時從 &mut T到 &U。
第一種情況表明如果有一個 &T,而T實現(xiàn)了返回U類型的Deref,則可以直接得到 &U。
第二種情況表明可變引用也有著相同的行為。
第三個情況將可變引用強轉(zhuǎn)為不可變引用。但是反過來是不行的,不可變引用永遠也不能強轉(zhuǎn)為可變引用。
這三種情況下,T類型都自動實現(xiàn)了U類型的所有方法。

(二)Drop Trait

Rust中的析構(gòu)函數(shù)是由Drop trait提供的drop()方法。
Drop Trait只有一個方法drop() 。
實現(xiàn)了Drop特質(zhì)的結(jié)構(gòu)體在離開了它的作用域時會調(diào)用drop()方法。
例子

use std::ops::Deref;
struct MyBox<T>(T);
impl<T> MyBox<T> {
     fn new(x:T)->MyBox<T>{
         MyBox(x)
     }
}
impl<T> Deref for MyBox<T> {
     type Target = T;
     fn deref(&self) -< &T {
         &self.0
     }
}
impl<T> Drop for MyBox<T>{
     fn drop(&mut self){
         println!("dropping MyBox object from memory ");
     }
}
fn main() {
     let x = 50;
     MyBox::new(x);
     MyBox::new("Hello");
}
編譯運行結(jié)果如下
dropping MyBox object from memory
dropping MyBox object from memory

到此這篇關于rust智能指針的具體使用的文章就介紹到這了,更多相關rust智能指針內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • rust多個mod文件引用和文件夾mod使用注意事項小結(jié)

    rust多個mod文件引用和文件夾mod使用注意事項小結(jié)

    在 Rust 項目中,可以使用 mod 關鍵字將一個文件夾或一個 rs 文件作為一個模塊引入到當前文件中,本文給大家介紹rust多個mod文件引用和文件夾mod使用注意事項小結(jié),感興趣的朋友跟隨小編一起看看吧
    2024-03-03
  • Rust 語言中的 into() 方法及代碼實例

    Rust 語言中的 into() 方法及代碼實例

    在 Rust 中,into() 方法通常用于將一個類型的值轉(zhuǎn)換為另一個類型,這通常涉及到資源的所有權轉(zhuǎn)移,本文給大家介紹Rust 語言中的 into() 方法及代碼實例,感謝的朋友跟隨小編一起看看吧
    2024-03-03
  • Rust突破編譯器限制構(gòu)造可修改的全局變量

    Rust突破編譯器限制構(gòu)造可修改的全局變量

    這篇文章主要為大家介紹了Rust突破編譯器限制構(gòu)造可修改的全局變量示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-10-10
  • Rust標量類型的具體使用

    Rust標量類型的具體使用

    本文主要介紹了Rust標量類型的具體使用,其中包括整數(shù)類型、浮點類型、布爾類型以及字符類型,具有一定的參考價值,感興趣的可以了解一下
    2024-03-03
  • 詳解Rust Substrate框架中的Runtime

    詳解Rust Substrate框架中的Runtime

    ubstrate是一個區(qū)塊鏈開發(fā)框架,它提供了一系列模塊化和可擴展的組件,可以幫助開發(fā)人員快速構(gòu)建自定義區(qū)塊鏈。 Runtime是Substrate區(qū)塊鏈的核心部分,文中有詳細的代碼示例,需要的朋友可以參考下
    2023-05-05
  • Rust 多線程編程的實現(xiàn)

    Rust 多線程編程的實現(xiàn)

    在rust中,多線程編程不算困難,但是也需要留心和別的編程語言中不同的地方,本文主要介紹了Rust 多線程編程的實現(xiàn),感興趣的可以了解一下
    2023-12-12
  • Rust日期與時間的操作方法

    Rust日期與時間的操作方法

    Rust的時間操作主要用到chrono庫,接下來我將簡單選一些常用的操作進行介紹,感興趣的朋友跟隨小編一起看看吧
    2023-09-09
  • Rust語言實現(xiàn)圖像編碼轉(zhuǎn)換

    Rust語言實現(xiàn)圖像編碼轉(zhuǎn)換

    image-rs庫是?Rust?社區(qū)中廣泛使用的一個開源庫,它提供了豐富的圖像編解碼功能,本文主要介紹了Rust語言實現(xiàn)圖像編碼轉(zhuǎn)換,具有一定的參考價值,感興趣的可以了解一下
    2024-05-05
  • 使用win10 wsl子系統(tǒng)如何將 rust 程序靜態(tài)編譯為linux可執(zhí)行文件

    使用win10 wsl子系統(tǒng)如何將 rust 程序靜態(tài)編譯為linux可執(zhí)行文件

    這篇文章主要介紹了使用win10 wsl子系統(tǒng)如何將 rust 程序靜態(tài)編譯為linux可執(zhí)行文件,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2025-05-05
  • Rust 標準庫的結(jié)構(gòu)及模塊路徑詳解

    Rust 標準庫的結(jié)構(gòu)及模塊路徑詳解

    在 Rust 中,標準庫提供了一組核心功能,以幫助開發(fā)者執(zhí)行常見的編程任務,這個路徑樹可以作為參考,幫助你更好地理解 Rust 標準庫的結(jié)構(gòu)和模塊之間的關系,本文介紹 Rust 標準庫的結(jié)構(gòu),并提供相應的 use 路徑,感興趣的朋友一起看看吧
    2024-05-05

最新評論