最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Rust常用特型之ToOwned特型示例詳解

 更新時間:2024年04月22日 09:32:23   作者:AiMateZero  
在Rust中,假定某類型實現(xiàn)了Clone特型,如果給你一個對它引用,那我們得到它指向內(nèi)容的備份的最常見方式是調(diào)用其clone()函數(shù),這篇文章主要介紹了Rust常用特型之ToOwned特型,需要的朋友可以參考下

在Rust標準庫中,存在很多常用的工具類特型,它們能幫助我們寫出更具有Rust風格的代碼。

ToOwned

這次我們來學一個和Borrow特型相關(guān)的特型,叫ToOwned類型??醋置嬉馑?code>Borrow是代表借出,而ToOwned代表去擁有它。

在Rust中,假定某類型實現(xiàn)了Clone特型,如果給你一個對它引用,那我們得到它指向內(nèi)容的備份的最常見方式是調(diào)用其clone()函數(shù)。但是如果你想克隆&str或者&[i32]時會發(fā)生什么呢?你的目的可能是想得到一個String或者Vec<i32>。但是根據(jù)Clone特型的定義,你無法得到它們。根據(jù)定義,對一個&T調(diào)用clone() 會返回一個T的值,也就是說會返回str或者[i32]。而我們前面學習Sized特型的時候提到過,str或者[i32] 是切片類型,無固定大小,是不能保存在變量中或者作為函數(shù)結(jié)果返回的。

std::borrow::ToOwned 特型提供了一個稍微寬松的方法將一引用轉(zhuǎn)換為可擁有的值。

trait ToOwned {
  type Owned: Borrow<Self>;
  fn to_owned(&self) -> Self::Owned;
}

上面的定義中,to_owned函數(shù)返回一個類型為Self::Owned的新鮮值,但是這個Owned可不是任意類型,它有個類型約束,也就是實現(xiàn)了Borrow<Self>. 也就是說A能借出B/&B(實現(xiàn)了Borrow<B>),B才能擁有A.

例如,你可以從Vec<T>中借出一個&[T](這里的泛型U 為 [T] ),因此[T]可以實現(xiàn)ToOwned<Owned=Vec<T>>,只要T實現(xiàn)了Clone特型。這里為什么要對T限制呢?畢竟你要得到一個備份,如果一個T不能克隆,那么這個備份是無法實現(xiàn)的,因為需要把切片的元素復制到新的向量中去。相似的,str實現(xiàn)了ToOwned<Owned=String>,因此我們可以調(diào)用&strto_owned函數(shù)得到一個全新的字符串。Path也實現(xiàn)了ToOwned<Owned=PathBuf>,我們也可以從Path引用中得到一個全新的PathBuf值。

Humble Cow

BorrowToOwned聯(lián)動可以實現(xiàn)一個很有意思的類型,Cow,注意它不是奶牛的意思,而是指 clone on write 我們趁熱來學習它。

充分利用 Rust 需要深思熟慮所有權(quán)問題,例如某個函數(shù)是否應該通過引用或值接收參數(shù)。通常你能確定使用其中的一種或者另一種(使用引用還是值),函數(shù)的參數(shù)類型代表了你的決定。但是存在這樣一些場景,你只有在運行時才知道到底是需要借用還是引用,這時,std::borrow::Cow類型就派上用場了,它的定義如下:

enum Cow<'a, B: ?Sized>
  where B: ToOwned
  {
  Borrowed(&'a B),
  Owned(<B as ToOwned>::Owned),
}

這里可以看到,Cow是一個枚舉,有兩個變量,分別代表借用和擁有。其Borrow變量綁定了一個&B(這里先忽視生命周期標記),這個B是個泛型,它的約束為B: ToOwned。它的目標類型我們先假定為U,那么U 必定實現(xiàn)了Borrow<B>

它的第二個枚舉變量為Owned,綁定了一個<B as ToOwned>::Owned的值,也就是U的值,所以Owned變量可以寫成Owned<U>。其中可以從U借出B,當然,也可以從B擁有U的新值。

第一個枚舉變量,是綁定了&B,因此我們可以很方便的得到&B,第二個變量,是綁定了U,然而U又可以借出B,因此我們?nèi)匀豢梢院苋菀椎牡玫?code>&B( 通過U的borrow() 函數(shù))。兩個變量都可以方便的得到&B,因此它也實現(xiàn)了Deref特型,這樣你可以直接在Cow上調(diào)用B的相關(guān)函數(shù),而不管Cow是借用了B還是擁有了U。

你還可以在Cow類型的值上調(diào)用to_mut函數(shù)得到一個&mut B。 如果Cow變量剛好好Borrowed,則to_mut函數(shù)會先調(diào)用&Bto_owned方法得到它自己擁有的一個U的Copy,并對原來的變量進行重新賦值,這樣就從Borrowed變量轉(zhuǎn)換成了Owned變量,然后再從新?lián)碛械腢的值中借出一個mut 引用。這里正是clone on write的含義所在(寫時clone).

我們來看一下這個Deref的實現(xiàn)代碼:

#[stable(feature = "rust1", since = "1.0.0")]
impl<B: ?Sized + ToOwned> Deref for Cow<'_, B>
where
    B::Owned: Borrow<B>,
{
    type Target = B;
    fn deref(&self) -> &B {
        match *self {
            Borrowed(borrowed) => borrowed,
            Owned(ref owned) => owned.borrow(),
        }
    }
}

你代碼中我們可以看到,如果Cow是引用 ,直接將這個引用返回,如果是擁有的U值,則從U值借出,這里有一個細節(jié):

Owned(ref owned) => owned.borrow(), 因為我們的deref函數(shù)接收參數(shù)為&self,因此我們無法在函數(shù)內(nèi)部消耗掉Cow本身,而match直接匹配時便會消耗這個值,因此為了阻止這種行為,添加了ref owned,代表這個owned只是獲取一個引用 ,因此這里的owned的類型其實為&U,所以直接調(diào)用其borrow()函數(shù)也就得到了一個&B. 注意borrow函數(shù)也是接收一個引用而非值作為參數(shù)。

to_mut函數(shù)的解釋為:

Acquires a mutable reference to the owned form of the data.

Clones the data if it is not already owned.

使用示例為:

use std::borrow::Cow;
let mut cow = Cow::Borrowed("foo");
cow.to_mut().make_ascii_uppercase();
assert_eq!(
  cow,
  Cow::Owned(String::from("FOO")) as Cow<'_, str>
);

通過上面的示例我們可以看到,就算我們的cow是Borrowed變量,擁有一個共享的引用,到最后也變成了一個Owned變量。

我們來看一下實現(xiàn)過程:

#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
    match *self {
        Borrowed(borrowed) => {
            *self = Owned(borrowed.to_owned());
            match *self {
                Borrowed(..) => unreachable!(),
                Owned(ref mut owned) => owned,
            }
        }
        Owned(ref mut owned) => owned,
    }
}

這里 如果是Borrowed,則首先會to_owned得到U的一個新值,然后再將self重新賦值為Owned,然后再重新對self進行match操作,

此時已經(jīng)是一個Owned,所以直接借出了ref mut,注意因為match操作會消耗值,所以這里的Owned(ref mut owned) => owned, 中加了ref 代表是一個引用,結(jié)合上例,我們就得到了一個&mut String。

相似的,Cow也實現(xiàn)了into_owned方法將引用轉(zhuǎn)換為一個擁有的值。如果必須,則可以將值的所有權(quán)轉(zhuǎn)移給調(diào)用者,在這個過程中Cow本身的值會被消耗掉。

Cow一個常見的用法是返回一個靜態(tài)的字符串文字值常量或者一個動態(tài)的字符串。例如,假定你需要將一個枚舉類型轉(zhuǎn)換成一個消息,枚舉的大多數(shù)變量都可用于固定的字符串,但是有一些變量或者一些額外的信息,因此你可以返回一個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()
    }
  }
}

上面的代碼使用了CowInto特型實現(xiàn)來構(gòu)造值。這里其實是CowFrom實現(xiàn),然后相對應的&str就有了Into實現(xiàn)。這個Match的絕大多數(shù)分支都返回一個靜態(tài)分配的文字串文本用于Cow::Borrowed綁定,只有最后一個分支返回一個String用于Owned變量綁定。

describe函數(shù)的調(diào)用者不用管返回的到底Cow的哪個變量,它只用簡單的將返回值看成是&str就行了,例如:

println!("Disaster has struck: {}", describe(&error));

如果你需要一個擁有的值,調(diào)用into_owned函數(shù)就可,例如 (describe(&error).into_owned() 就返回一個String。

使用Cow可以讓describle函數(shù)和它的調(diào)用者直到在需要時才會分配內(nèi)存來保存新生成的字符串。

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

您可能感興趣的文章:

相關(guān)文章

  • Rust語言之Prometheus系統(tǒng)監(jiān)控工具包的使用詳解

    Rust語言之Prometheus系統(tǒng)監(jiān)控工具包的使用詳解

    Prometheus?是一個開源的系統(tǒng)監(jiān)控和警報工具包,最初是由SoundCloud構(gòu)建的,隨著時間的發(fā)展,Prometheus已經(jīng)具有適用于各種使用場景的版本,為了開發(fā)者方便開發(fā),更是有各種語言版本的Prometheus的開發(fā)工具包,本文主要介紹Rust版本的Prometheus開發(fā)工具包
    2023-10-10
  • 關(guān)于rust的模塊引入問題

    關(guān)于rust的模塊引入問題

    Rust 語言是一種高效、可靠的通用高級語言,它的執(zhí)行效率也是令人稱贊的,是一種少有的兼顧開發(fā)效率和執(zhí)行效率的語言,這篇文章主要介紹了rust的模塊引入相關(guān)知識,需要的朋友可以參考下
    2022-10-10
  • 利用rust實現(xiàn)一個命令行工具

    利用rust實現(xiàn)一個命令行工具

    這篇文章主要為大家詳細介紹了如何使用?Rust?和?clap?4.4.0?創(chuàng)建一個命令行工具?my_dev_tool,文中的示例代碼講解詳細,需要的小伙伴可以參考下
    2023-12-12
  • Rust泛型編程深入實例介紹應用技巧

    Rust泛型編程深入實例介紹應用技巧

    這篇文章主要介紹了Rust泛型編程,泛型是Rust中一種強大的特性,它允許我們編寫通用的代碼,適用于不同類型,通過掌握泛型的高級應用,我們可以編寫更加靈活、可復用的代碼,需要的朋友可以參考下
    2026-05-05
  • Rust語言之使用Polar權(quán)限管理方法詳解

    Rust語言之使用Polar權(quán)限管理方法詳解

    權(quán)限管理 (Permission Management) 是一個涵蓋了系統(tǒng)或網(wǎng)絡中用戶權(quán)限控制和管理的系統(tǒng),本文將詳細給大家介紹Rust語言中如何使用Polar權(quán)限管理,需要的朋友可以參考下
    2023-11-11
  • Rust 語言中的dyn 關(guān)鍵字及用途解析

    Rust 語言中的dyn 關(guān)鍵字及用途解析

    在Rust中,"dyn"關(guān)鍵字用于表示動態(tài)分發(fā)(dynamic dispatch),它通常與trait對象一起使用,以實現(xiàn)運行時多態(tài), 在Rust中,多態(tài)是通過trait和impl來實現(xiàn)的,這篇文章主要介紹了Rust 語言中的 dyn 關(guān)鍵字,需要的朋友可以參考下
    2024-03-03
  • Rust語言中級教程之指針

    Rust語言中級教程之指針

    Rust中共有三種類型的指針,分別為引用,解引用,智能指針,這篇文章主要介紹了Rust語言中級教程之指針,需要的朋友可以參考下
    2023-05-05
  • Rust cargo 命令行工具使用示例教程

    Rust cargo 命令行工具使用示例教程

    cargo 是 Rust 的構(gòu)建系統(tǒng)和包管理器,負責創(chuàng)建項目、編譯代碼、管理依賴、運行測試等,是日常開發(fā)中最常用的工具,這篇文章主要介紹了Rust cargo 命令行工具使用教程,需要的朋友可以參考下
    2025-04-04
  • Rust實現(xiàn)AES加解密詳解

    Rust實現(xiàn)AES加解密詳解

    這篇文章主要為大家詳細介紹了如何利用Rust語言實現(xiàn)AES加解密算法,文中的示例代碼講解詳細,具有一定的借鑒價值,需要的可以了解一下
    2022-10-10
  • Rust中箱、包和模塊的學習筆記

    Rust中箱、包和模塊的學習筆記

    Rust中有三個重要的組織概念:箱、包、模塊,本文主要介紹了Rust中箱、包和模塊的學習筆記,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧
    2024-03-03

最新評論

金乡县| 乌什县| 广州市| 饶河县| 梨树县| 昌江| 无锡市| 万源市| 泽普县| 都江堰市| 卓资县| 淮滨县| 昭平县| 监利县| 荣昌县| 岚皋县| 银川市| 通化市| 霸州市| 静海县| 临城县| 谢通门县| 黄石市| 化州市| 宁阳县| 西乌珠穆沁旗| 双桥区| 天全县| 武强县| 和顺县| 彰化县| 武夷山市| 乌拉特中旗| 哈巴河县| 巴南区| 正蓝旗| 博湖县| 大新县| 前郭尔| 延寿县| 察隅县|