国产gaysexchina男同gay,japanrcep老熟妇乱子伦视频,吃奶呻吟打开双腿做受动态图,成人色网站,国产av一区二区三区最新精品

Rust 使用 Drop Trait 運行清理代碼

2023-03-22 15:13 更新
ch15-03-drop.md
commit d44317c3122b44fb713aba66cc295dee3453b24b

對于智能指針模式來說第二個重要的 trait 是 Drop,其允許我們在值要離開作用域時執(zhí)行一些代碼??梢詾槿魏晤愋吞峁?nbsp;Drop trait 的實現(xiàn),同時所指定的代碼被用于釋放類似于文件或網(wǎng)絡(luò)連接的資源。我們在智能指針上下文中討論 Drop 是因為其功能幾乎總是用于實現(xiàn)智能指針。例如,當(dāng) Box<T> 被丟棄時會釋放 box 指向的堆空間。

在其他一些語言中,我們不得不記住在每次使用完智能指針實例后調(diào)用清理內(nèi)存或資源的代碼。如果忘記的話,運行代碼的系統(tǒng)可能會因為負荷過重而崩潰。在 Rust 中,可以指定每當(dāng)值離開作用域時被執(zhí)行的代碼,編譯器會自動插入這些代碼。于是我們就不需要在程序中到處編寫在實例結(jié)束時清理這些變量的代碼 —— 而且還不會泄漏資源。

指定在值離開作用域時應(yīng)該執(zhí)行的代碼的方式是實現(xiàn) Drop trait。Drop trait 要求實現(xiàn)一個叫做 drop 的方法,它獲取一個 self 的可變引用。為了能夠看出 Rust 何時調(diào)用 drop,讓我們暫時使用 println! 語句實現(xiàn) drop

示例 15-14 展示了唯一定制功能就是當(dāng)其實例離開作用域時,打印出 Dropping CustomSmartPointer! 的結(jié)構(gòu)體 CustomSmartPointer。這會演示 Rust 何時運行 drop 函數(shù):

文件名: src/main.rs

struct CustomSmartPointer {
    data: String,
}

impl Drop for CustomSmartPointer {
    fn drop(&mut self) {
        println!("Dropping CustomSmartPointer with data `{}`!", self.data);
    }
}

fn main() {
    let c = CustomSmartPointer {
        data: String::from("my stuff"),
    };
    let d = CustomSmartPointer {
        data: String::from("other stuff"),
    };
    println!("CustomSmartPointers created.");
}

示例 15-14:結(jié)構(gòu)體 CustomSmartPointer,其實現(xiàn)了放置清理代碼的 Drop trait

Drop trait 包含在 prelude 中,所以無需導(dǎo)入它。我們在 CustomSmartPointer 上實現(xiàn)了 Drop trait,并提供了一個調(diào)用 println! 的 drop 方法實現(xiàn)。drop 函數(shù)體是放置任何當(dāng)類型實例離開作用域時期望運行的邏輯的地方。這里選擇打印一些文本以展示 Rust 何時調(diào)用 drop。

在 main 中,我們新建了兩個 CustomSmartPointer 實例并打印出了 CustomSmartPointer created.。在 main 的結(jié)尾,CustomSmartPointer 的實例會離開作用域,而 Rust 會調(diào)用放置于 drop 方法中的代碼,打印出最后的信息。注意無需顯式調(diào)用 drop 方法:

當(dāng)運行這個程序,會出現(xiàn)如下輸出:

$ cargo run
   Compiling drop-example v0.1.0 (file:///projects/drop-example)
    Finished dev [unoptimized + debuginfo] target(s) in 0.60s
     Running `target/debug/drop-example`
CustomSmartPointers created.
Dropping CustomSmartPointer with data `other stuff`!
Dropping CustomSmartPointer with data `my stuff`!

當(dāng)實例離開作用域 Rust 會自動調(diào)用 drop,并調(diào)用我們指定的代碼。變量以被創(chuàng)建時相反的順序被丟棄,所以 d 在 c 之前被丟棄。這個例子剛好給了我們一個 drop 方法如何工作的可視化指導(dǎo),不過通常需要指定類型所需執(zhí)行的清理代碼而不是打印信息。

通過 std::mem::drop 提早丟棄值

不幸的是,我們并不能直截了當(dāng)?shù)慕?nbsp;drop 這個功能。通常也不需要禁用 drop ;整個 Drop trait 存在的意義在于其是自動處理的。然而,有時你可能需要提早清理某個值。一個例子是當(dāng)使用智能指針管理鎖時;你可能希望強制運行 drop 方法來釋放鎖以便作用域中的其他代碼可以獲取鎖。Rust 并不允許我們主動調(diào)用 Drop trait 的 drop 方法;當(dāng)我們希望在作用域結(jié)束之前就強制釋放變量的話,我們應(yīng)該使用的是由標(biāo)準庫提供的 std::mem::drop。

如果我們像是示例 15-14 那樣嘗試調(diào)用 Drop trait 的 drop 方法,就會得到像示例 15-15 那樣的編譯錯誤:

文件名: src/main.rs

fn main() {
    let c = CustomSmartPointer {
        data: String::from("some data"),
    };
    println!("CustomSmartPointer created.");
    c.drop();
    println!("CustomSmartPointer dropped before the end of main.");
}

示例 15-15:嘗試手動調(diào)用 Drop trait 的 drop 方法提早清理

如果嘗試編譯代碼會得到如下錯誤:

$ cargo run
   Compiling drop-example v0.1.0 (file:///projects/drop-example)
error[E0040]: explicit use of destructor method
  --> src/main.rs:16:7
   |
16 |     c.drop();
   |     --^^^^--
   |     | |
   |     | explicit destructor calls not allowed
   |     help: consider using `drop` function: `drop(c)`

For more information about this error, try `rustc --explain E0040`.
error: could not compile `drop-example` due to previous error

錯誤信息表明不允許顯式調(diào)用 drop。錯誤信息使用了術(shù)語 析構(gòu)函數(shù)destructor),這是一個清理實例的函數(shù)的通用編程概念。析構(gòu)函數(shù) 對應(yīng)創(chuàng)建實例的 構(gòu)造函數(shù)。Rust 中的 drop 函數(shù)就是這么一個析構(gòu)函數(shù)。

Rust 不允許我們顯式調(diào)用 drop 因為 Rust 仍然會在 main 的結(jié)尾對值自動調(diào)用 drop,這會導(dǎo)致一個 double free 錯誤,因為 Rust 會嘗試清理相同的值兩次。

因為不能禁用當(dāng)值離開作用域時自動插入的 drop,并且不能顯式調(diào)用 drop,如果我們需要強制提早清理值,可以使用 std::mem::drop 函數(shù)。

std::mem::drop 函數(shù)不同于 Drop trait 中的 drop 方法??梢酝ㄟ^傳遞希望提早強制丟棄的值作為參數(shù)。std::mem::drop 位于 prelude,所以我們可以修改示例 15-15 中的 main 來調(diào)用 drop 函數(shù)。如示例 15-16 所示:

文件名: src/main.rs

fn main() {
    let c = CustomSmartPointer {
        data: String::from("some data"),
    };
    println!("CustomSmartPointer created.");
    drop(c);
    println!("CustomSmartPointer dropped before the end of main.");
}

示例 15-16: 在值離開作用域之前調(diào)用 std::mem::drop 顯式清理

運行這段代碼會打印出如下:

$ cargo run
   Compiling drop-example v0.1.0 (file:///projects/drop-example)
    Finished dev [unoptimized + debuginfo] target(s) in 0.73s
     Running `target/debug/drop-example`
CustomSmartPointer created.
Dropping CustomSmartPointer with data `some data`!
CustomSmartPointer dropped before the end of main.

Dropping CustomSmartPointer with data `some data`! 出現(xiàn)在 CustomSmartPointer created. 和 CustomSmartPointer dropped before the end of main. 之間,表明了 drop 方法被調(diào)用了并在此丟棄了 c

Drop trait 實現(xiàn)中指定的代碼可以用于許多方面,來使得清理變得方便和安全:比如可以用其創(chuàng)建我們自己的內(nèi)存分配器!通過 Drop trait 和 Rust 所有權(quán)系統(tǒng),你無需擔(dān)心之后的代碼清理,Rust 會自動考慮這些問題。

我們也無需擔(dān)心意外的清理掉仍在使用的值,這會造成編譯器錯誤:所有權(quán)系統(tǒng)確保引用總是有效的,也會確保 drop 只會在值不再被使用時被調(diào)用一次。

現(xiàn)在我們學(xué)習(xí)了 Box<T> 和一些智能指針的特性,讓我們聊聊標(biāo)準庫中定義的其他幾種智能指針。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號