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

Rust?中?Deref?Coercion講解

 更新時間:2022年10月26日 10:50:14   作者:aggresss  
Rust 的設(shè)計理念一向是顯式比隱式好,也就是說所有的行為盡量在代碼中表現(xiàn)出來,這篇文章主要介紹了Rust?中?Deref?Coercion?介紹,需要的朋友可以參考下

0x00 前言

寫這個文檔的初衷是因為在中文社區(qū)看到一個非常不負責任的翻譯,將 “implicit deref coercion” 翻譯成 “隱式 deref 強制”,于是覺得有必要記錄一下,以防止后來的新手在這里翻車。
首先需要解釋一下 “coercion” 在編程語言文檔中尤其是涉及到類型轉(zhuǎn)換時的中文意思。
類型轉(zhuǎn)換 (type conversion) 包括顯式指定被轉(zhuǎn)換到的類型的顯式轉(zhuǎn)換 (explicit conversion) 或稱 cast,以及與之相對的隱式轉(zhuǎn)換 (implicit conversion) 或稱 coercion。因為翻譯不準等原因,這兩者之間經(jīng)常被混淆。
cast 和 coercion 同時出現(xiàn)的時候,中文把前者翻譯成 “顯式類型轉(zhuǎn)換”,后者翻譯成 “隱式類型轉(zhuǎn)換”。

Rust 的設(shè)計理念一向是顯式比隱式好,也就是說所有的行為盡量在代碼中表現(xiàn)出來。但也是有例外的,例如接下來我們要討論的兩個話題。

0x01 Deref Trait

Rust 中有一對運算符 &*,分別表示對一個變量的引用和解引用。
例如下面的代碼:

fn main() {
    let x = 5;
    let y = &x;

    assert_eq!(5, x);
    assert_eq!(5, *y);
}

如果按照 C 語言的思維方式,這兩個操作符是互補的,即互為逆操作,但在 Rust 中并不適用。當一個類型實現(xiàn)了 Deref 這個 Trait 后,對該類型顯式執(zhí)行 *y 操作時,Rust 將隱式執(zhí)行 *(y.deref()) 。
如果沒有實現(xiàn) Deref trait,只有引用類型可以被解引用,而實現(xiàn)了 Deref trait 后,編譯器將隱式執(zhí)行 deref 決定返回怎樣的引用類型。

Deref Trait 的定義如下:

pub trait Deref {
    type Target: ?Sized;

    fn deref(&self) -> &Self::Target;
}

有一個很有趣的點,雖然是 Deref 操作,但是返回類型卻是一個引用類型。這個在官方文檔中給出了解釋:

The reason the deref method returns a reference to a value, and that the plain dereference outside the parentheses in *(y.deref()) is still necessary, is to do with the ownership system. If the deref method returned the value directly instead of a reference to the value, the value would be moved out of self. We don’t want to take ownership of the inner value inside MyBox in this case or in most cases where we use the dereference operator.

主要原因是為了與大多數(shù)場景下的 ownership 機制適配。

通過了解 Rust 的 Deref Trait 后,我們可以得出結(jié)論:在 Rust 中 *&T&*T 不一定是同一個類型,例如下面示例:

use std::ops::Deref;

#[derive(Copy, Clone, Debug)]
struct MyBox {
    alpha: i32,
}

impl Deref for MyBox {
    type Target = i32;

    fn deref(&self) -> &Self::Target {
        &self.alpha
    }
}

fn main() {
    let beta = MyBox { alpha: 32 };
    let gamma = &*beta; // &i32
    let delta = *β // Mybox
    println!("{:?}, {:?}", gamma, delta);
}

0x02 Implicit Deref Coercion

Deref coercion converts a reference to a type that implements the Deref trait into a reference to another type.

最初接觸到 Deref coercion 的場景通常是使用 &str 作為參數(shù)的函數(shù),傳入 &String 是可以編譯通過的,習慣了 Rust 大爺苛刻的編譯器后覺得這不可思議,深入了解后才知道,Rust 內(nèi)部實現(xiàn)了 String 類型的 Deref trait,并且 type Target = &str
當引用作為函數(shù)或方法的參數(shù)時,Rust 編譯器將隱式執(zhí)行 deref coercion,以找到適配的類型。這樣省去了 *& 的繁瑣操作,但講真對新手確實不友好。下面是一個示例:

fn hello(name: &str) {
    println!("Hello, {name}!");
}

struct MyBox<T>(T);

impl<T> MyBox<T> {
    fn new(x: T) -> MyBox<T> {
        MyBox(x)
    }
}

use std::ops::Deref;

impl<T> Deref for MyBox<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

fn main() {
    let m = MyBox::new(String::from("Rust"));
    hello(&m);
}

再看一個有意思的示例:

fn main() {
    let s = "Hello, Rust!";
    println!("length: {}", s.len());
    println!("length: {}", (&s).len());
    println!("length: {}", (&&&&&&&&&&&&&s).len());
}

上面的示例是可以編譯通過的,我們?nèi)绻褂?&&&&&&&&&&str 類型來調(diào)用成員方法,也是可以的。原因是 Rust 編譯器的 deref coercion 是遞歸的,當它找不到這個成員方法的時候會自動嘗試使用 deref() 方法后再找該方法,一直遞歸下去。編譯器在&&&str 類型里面找不到 len 方法,就嘗試將它 deref(),變成 &&str 類型,再尋找 len 方法,還是沒找到,那么繼續(xù) deref(),變成 &str,現(xiàn)在找到 len 方法了,于是就調(diào)用這個方法。

0x03 Option 中的 as_deref()

熟練的使用 Option 可以在 Rust 開發(fā)中節(jié)省很多頭發(fā)。當需要將 Option<T> 轉(zhuǎn)化為 Option<&T> 時,我們通常使用 Option.as_ref() 操作,再結(jié)合 map() 方法可以在不轉(zhuǎn)移所有權(quán)的情況下使用 Option 中的變量。當看到 Option.as_deref() 操作時,我們首先會望文生義的認為是將 Option<&T> 轉(zhuǎn)化為 Option<T>,但理解了前兩節(jié)的內(nèi)容后會懂得 Option.as_deref() 的操作其實是 Option.as_ref().map(|s| s.deref()) 的簡寫形式,返回的仍然是一個引用,目的是為了使用 Rust 中的 deref coercion 機制。

參考文檔

https://doc.rust-lang.org/std/ops/trait.Deref.html
https://doc.rust-lang.org/book/ch15-02-deref.html
https://stackoverflow.com/questions/8857763/what-is-the-difference-between-casting-and-coercing
https://mp.weixin.qq.com/s/G28XE1rfX0nT6zIi86ji0Q
https://blog.csdn.net/weixin_39702559/article/details/112276392
https://blog.csdn.net/JAN6055/article/details/125774473

到此這篇關(guān)于Rust 中 Deref Coercion 介紹的文章就介紹到這了,更多相關(guān)Rust  Deref Coercion內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用cargo install安裝Rust二進制工具過程

    使用cargo install安裝Rust二進制工具過程

    cargoinstall是一個用于安裝包含可執(zhí)行目標的Rust包的命令行工具,類似于系統(tǒng)軟件包管理器,但它為Rust開發(fā)者提供了一種簡潔的方式來安裝和管理命令行工具,安裝后,二進制文件會存儲在$HOME/.cargo/bin目錄中,需要將該目錄添加到$PATH環(huán)境變量中才能在命令行中直接運行
    2025-02-02
  • Rust調(diào)用函數(shù)操作符?.?和?::?的區(qū)別詳解

    Rust調(diào)用函數(shù)操作符?.?和?::?的區(qū)別詳解

    在Rust中,.和::操作符都可以用來調(diào)用方法,但它們的用法有所不同,所以本文就將詳細的給大家介紹一下.和::操作符的區(qū)別,感興趣的同學(xué)跟著小編一起來學(xué)習吧
    2023-07-07
  • 詳解在Rust語言中如何聲明可變的static類型變量

    詳解在Rust語言中如何聲明可變的static類型變量

    在Rust中,可以使用lazy_static宏來聲明可變的靜態(tài)變量,lazy_static是一個用于聲明延遲求值靜態(tài)變量的宏,本文將通過一個簡單的例子,演示如何使用?lazy_static?宏來聲明一個可變的靜態(tài)變量,需要的朋友可以參考下
    2023-08-08
  • Rust 枚舉和模式匹配的實現(xiàn)

    Rust 枚舉和模式匹配的實現(xiàn)

    枚舉是 Rust 中非常重要的復(fù)合類型,也是最強大的復(fù)合類型之一,廣泛用于屬性配置、錯誤處理、分支流程、類型聚合等場景中,本文就來介紹一下Rust 枚舉和模式匹配,感興趣的可以了解一下
    2023-12-12
  • rust類型轉(zhuǎn)換的實現(xiàn)

    rust類型轉(zhuǎn)換的實現(xiàn)

    Rust是類型安全的語言,因此在Rust中做類型轉(zhuǎn)換不是一件簡單的事,本文主要介紹了rust類型轉(zhuǎn)換的實現(xiàn),具有一定的參考價值,感興趣的可以了解一下
    2023-12-12
  • Rust語言數(shù)據(jù)類型的具體使用

    Rust語言數(shù)據(jù)類型的具體使用

    在Rust中,每個值都有一個明確的數(shù)據(jù)類型,本文主要介紹了Rust語言數(shù)據(jù)類型的具體使用,具有一定的參考價值,感興趣的可以了解一下
    2024-04-04
  • Rust動態(tài)調(diào)用字符串定義的Rhai函數(shù)方式

    Rust動態(tài)調(diào)用字符串定義的Rhai函數(shù)方式

    Rust中使用Rhai動態(tài)調(diào)用字符串定義的函數(shù),通過eval_expression_with_scope實現(xiàn),但參數(shù)傳遞和函數(shù)名處理有局限性,使用FnCall功能更健壯,但更復(fù)雜,總結(jié)提供了更通用的方法,但需要處理更多錯誤情況
    2025-02-02
  • Rust?Atomics?and?Locks?源碼解讀

    Rust?Atomics?and?Locks?源碼解讀

    這篇文章主要為大家介紹了Rust?Atomics?and?Locks?源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-02-02
  • Rust循環(huán)控制結(jié)構(gòu)用法詳解

    Rust循環(huán)控制結(jié)構(gòu)用法詳解

    Rust提供了多種形式的循環(huán)結(jié)構(gòu),每種都適用于不同的場景,在Rust中,循環(huán)有三種主要的形式:loop、while和for,本文將介紹Rust中的這三種循環(huán),并通過實例展示它們的用法和靈活性,感興趣的朋友一起看看吧
    2024-02-02
  • 教你使用RustDesk?搭建一個自己的遠程桌面中繼服務(wù)器

    教你使用RustDesk?搭建一個自己的遠程桌面中繼服務(wù)器

    這篇文章主要介紹了RustDesk?搭建一個自己的遠程桌面中繼服務(wù)器,主要包括服務(wù)端安裝和客戶端配置方法,配置好相關(guān)操作輸入控制碼即可發(fā)起遠程或文件傳輸,本文通過圖文給大家講解的非常詳細,需要的朋友可以參考下
    2022-08-08

最新評論