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

Rust 結(jié)構(gòu)體示例程序

2023-03-22 15:09 更新
ch05-02-example-structs.md
commit dd7e05275822d6cf790bcdae6983b3234141b5e7

為了理解何時(shí)會(huì)需要使用結(jié)構(gòu)體,讓我們編寫(xiě)一個(gè)計(jì)算長(zhǎng)方形面積的程序。我們會(huì)從單獨(dú)的變量開(kāi)始,接著重構(gòu)程序直到使用結(jié)構(gòu)體替代他們?yōu)橹埂?br>

使用 Cargo 新建一個(gè)叫做 rectangles 的二進(jìn)制程序,它獲取以像素為單位的長(zhǎng)方形的寬度和高度,并計(jì)算出長(zhǎng)方形的面積。示例 5-8 顯示了位于項(xiàng)目的 src/main.rs 中的小程序,它剛剛好實(shí)現(xiàn)此功能:

文件名: src/main.rs

fn main() {
    let width1 = 30;
    let height1 = 50;

    println!(
        "The area of the rectangle is {} square pixels.",
        area(width1, height1)
    );
}

fn area(width: u32, height: u32) -> u32 {
    width * height
}

示例 5-8:通過(guò)分別指定長(zhǎng)方形的寬和高的變量來(lái)計(jì)算長(zhǎng)方形面積

現(xiàn)在使用 cargo run 運(yùn)行程序:

$ cargo run
   Compiling rectangles v0.1.0 (file:///projects/rectangles)
    Finished dev [unoptimized + debuginfo] target(s) in 0.42s
     Running `target/debug/rectangles`
The area of the rectangle is 1500 square pixels.

這個(gè)示例代碼在調(diào)用 area 函數(shù)時(shí)傳入每個(gè)維度,雖然可以正確計(jì)算出長(zhǎng)方形的面積,但我們?nèi)匀豢梢孕薷倪@段代碼來(lái)使它的意義更加明確,并且增加可讀性。

這些代碼的問(wèn)題突顯在 area 的簽名上:

fn area(width: u32, height: u32) -> u32 {

函數(shù) area 本應(yīng)該計(jì)算一個(gè)長(zhǎng)方形的面積,不過(guò)函數(shù)卻有兩個(gè)參數(shù)。這兩個(gè)參數(shù)是相關(guān)聯(lián)的,不過(guò)程序本身卻沒(méi)有表現(xiàn)出這一點(diǎn)。將長(zhǎng)度和寬度組合在一起將更易懂也更易處理。第三章的 “元組類(lèi)型” 部分已經(jīng)討論過(guò)了一種可行的方法:元組。

使用元組重構(gòu)

示例 5-9 展示了使用元組的另一個(gè)程序版本。

文件名: src/main.rs

fn main() {
    let rect1 = (30, 50);

    println!(
        "The area of the rectangle is {} square pixels.",
        area(rect1)
    );
}

fn area(dimensions: (u32, u32)) -> u32 {
    dimensions.0 * dimensions.1
}

示例 5-9:使用元組來(lái)指定長(zhǎng)方形的寬高

在某種程度上說(shuō),這個(gè)程序更好一點(diǎn)了。元組幫助我們?cè)黾恿艘恍┙Y(jié)構(gòu)性,并且現(xiàn)在只需傳一個(gè)參數(shù)。不過(guò)在另一方面,這個(gè)版本卻有一點(diǎn)不明確了:元組并沒(méi)有給出元素的名稱(chēng),所以計(jì)算變得更費(fèi)解了,因?yàn)椴坏貌皇褂盟饕齺?lái)獲取元組的每一部分:

在計(jì)算面積時(shí)將寬和高弄混倒無(wú)關(guān)緊要,不過(guò)當(dāng)在屏幕上繪制長(zhǎng)方形時(shí)就有問(wèn)題了!我們必須牢記 width 的元組索引是 0height 的元組索引是 1。如果其他人要使用這些代碼,他們必須要搞清楚這一點(diǎn),并也要牢記于心。很容易忘記或者混淆這些值而造成錯(cuò)誤,因?yàn)槲覀儧](méi)有在代碼中傳達(dá)數(shù)據(jù)的意圖。

使用結(jié)構(gòu)體重構(gòu):賦予更多意義

我們使用結(jié)構(gòu)體為數(shù)據(jù)命名來(lái)為其賦予意義。我們可以將我們正在使用的元組轉(zhuǎn)換成一個(gè)有整體名稱(chēng)而且每個(gè)部分也有對(duì)應(yīng)名字的結(jié)構(gòu)體,如示例 5-10 所示:

文件名: src/main.rs

struct Rectangle {
    width: u32,
    height: u32,
}

fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };

    println!(
        "The area of the rectangle is {} square pixels.",
        area(&rect1)
    );
}

fn area(rectangle: &Rectangle) -> u32 {
    rectangle.width * rectangle.height
}

示例 5-10:定義 Rectangle 結(jié)構(gòu)體

這里我們定義了一個(gè)結(jié)構(gòu)體并稱(chēng)其為 Rectangle。在大括號(hào)中定義了字段 width 和 height,類(lèi)型都是 u32。接著在 main 中,我們創(chuàng)建了一個(gè)具體的 Rectangle 實(shí)例,它的寬是 30,高是 50。

函數(shù) area 現(xiàn)在被定義為接收一個(gè)名叫 rectangle 的參數(shù),其類(lèi)型是一個(gè)結(jié)構(gòu)體 Rectangle 實(shí)例的不可變借用。第四章講到過(guò),我們希望借用結(jié)構(gòu)體而不是獲取它的所有權(quán),這樣 main 函數(shù)就可以保持 rect1 的所有權(quán)并繼續(xù)使用它,所以這就是為什么在函數(shù)簽名和調(diào)用的地方會(huì)有 &

area 函數(shù)訪問(wèn) Rectangle 實(shí)例的 width 和 height 字段(注意,訪問(wèn)對(duì)結(jié)構(gòu)體的引用的字段不會(huì)移動(dòng)字段的所有權(quán),這就是為什么你經(jīng)??吹綄?duì)結(jié)構(gòu)體的引用)。area 的函數(shù)簽名現(xiàn)在明確的闡述了我們的意圖:使用 Rectangle 的 width 和 height 字段,計(jì)算 Rectangle 的面積。這表明寬高是相互聯(lián)系的,并為這些值提供了描述性的名稱(chēng)而不是使用元組的索引值 0 和 1 。結(jié)構(gòu)體勝在更清晰明了。

通過(guò)派生 trait 增加實(shí)用功能

在調(diào)試程序時(shí)打印出 Rectangle 實(shí)例來(lái)查看其所有字段的值非常有用。示例 5-11 像前面章節(jié)那樣嘗試使用 println! 宏。但這并不行。

文件名: src/main.rs

struct Rectangle {
    width: u32,
    height: u32,
}

fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };

    println!("rect1 is {}", rect1);
}

示例 5-11:嘗試打印出 Rectangle 實(shí)例

當(dāng)我們運(yùn)行這個(gè)代碼時(shí),會(huì)出現(xiàn)帶有如下核心信息的錯(cuò)誤:

error[E0277]: `Rectangle` doesn't implement `std::fmt::Display`

println! 宏能處理很多類(lèi)型的格式,不過(guò),{} 默認(rèn)告訴 println! 使用被稱(chēng)為 Display 的格式:意在提供給直接終端用戶查看的輸出。目前為止見(jiàn)過(guò)的基本類(lèi)型都默認(rèn)實(shí)現(xiàn)了 Display,因?yàn)樗褪窍蛴脩粽故?nbsp;1 或其他任何基本類(lèi)型的唯一方式。不過(guò)對(duì)于結(jié)構(gòu)體,println! 應(yīng)該用來(lái)輸出的格式是不明確的,因?yàn)檫@有更多顯示的可能性:是否需要逗號(hào)?需要打印出大括號(hào)嗎?所有字段都應(yīng)該顯示嗎?由于這種不確定性,Rust 不會(huì)嘗試猜測(cè)我們的意圖,所以結(jié)構(gòu)體并沒(méi)有提供一個(gè) Display 實(shí)現(xiàn)來(lái)使用 println! 與 {} 占位符。

但是如果我們繼續(xù)閱讀錯(cuò)誤,將會(huì)發(fā)現(xiàn)這個(gè)有幫助的信息:

   = help: the trait `std::fmt::Display` is not implemented for `Rectangle`
   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead

讓我們來(lái)試試!現(xiàn)在 println! 宏調(diào)用看起來(lái)像 println!("rect1 is {:?}", rect1); 這樣。在 {} 中加入 :? 指示符告訴 println! 我們想要使用叫做 Debug 的輸出格式。Debug 是一個(gè) trait,它允許我們以一種對(duì)開(kāi)發(fā)者有幫助的方式打印結(jié)構(gòu)體,以便當(dāng)我們調(diào)試代碼時(shí)能看到它的值。

這樣調(diào)整后再次運(yùn)行程序。見(jiàn)鬼了!仍然能看到一個(gè)錯(cuò)誤:

error[E0277]: `Rectangle` doesn't implement `Debug`

不過(guò)編譯器又一次給出了一個(gè)有幫助的信息:

   = help: the trait `Debug` is not implemented for `Rectangle`
   = note: add `#[derive(Debug)]` to `Rectangle` or manually `impl Debug for Rectangle`

Rust 確實(shí) 包含了打印出調(diào)試信息的功能,不過(guò)我們必須為結(jié)構(gòu)體顯式選擇這個(gè)功能。為此,在結(jié)構(gòu)體定義之前加上外部屬性 #[derive(Debug)],如示例 5-12 所示:

文件名: src/main.rs

#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };

    println!("rect1 is {:?}", rect1);
}

示例 5-12:增加屬性來(lái)派生 Debug trait,并使用調(diào)試格式打印 Rectangle 實(shí)例

現(xiàn)在我們?cè)龠\(yùn)行這個(gè)程序時(shí),就不會(huì)有任何錯(cuò)誤,并會(huì)出現(xiàn)如下輸出:

$ cargo run
   Compiling rectangles v0.1.0 (file:///projects/rectangles)
    Finished dev [unoptimized + debuginfo] target(s) in 0.48s
     Running `target/debug/rectangles`
rect1 is Rectangle { width: 30, height: 50 }

好極了!這并不是最漂亮的輸出,不過(guò)它顯示這個(gè)實(shí)例的所有字段,毫無(wú)疑問(wèn)這對(duì)調(diào)試有幫助。當(dāng)我們有一個(gè)更大的結(jié)構(gòu)體時(shí),能有更易讀一點(diǎn)的輸出就好了,為此可以使用 {:#?} 替換 println! 字符串中的 {:?}。在這個(gè)例子中使用 {:#?} 風(fēng)格將會(huì)輸出:

$ cargo run
   Compiling rectangles v0.1.0 (file:///projects/rectangles)
    Finished dev [unoptimized + debuginfo] target(s) in 0.48s
     Running `target/debug/rectangles`
rect1 is Rectangle {
    width: 30,
    height: 50,
}

另一種使用 Debug 格式打印數(shù)值的方法是使用 dbg! 宏。dbg! 宏接收一個(gè)表達(dá)式的所有權(quán)(與 println! 宏相反,后者接收的是引用),打印出代碼中調(diào)用 dbg! 宏時(shí)所在的文件和行號(hào),以及該表達(dá)式的結(jié)果值,并返回該值的所有權(quán)。

注意:調(diào)用 ?dbg!? 宏會(huì)打印到標(biāo)準(zhǔn)錯(cuò)誤控制臺(tái)流(?stderr?),與 ?println!? 不同,后者會(huì)打印到標(biāo)準(zhǔn)輸出控制臺(tái)流(?stdout?)。我們將在第十二章 “將錯(cuò)誤信息寫(xiě)入標(biāo)準(zhǔn)錯(cuò)誤而不是標(biāo)準(zhǔn)輸出” 一節(jié)中更多地討論 ?stderr ?和 ?stdout?。

下面是一個(gè)例子,我們對(duì)分配給 width 字段的值以及 rect1 中整個(gè)結(jié)構(gòu)的值感興趣。

#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

fn main() {
    let scale = 2;
    let rect1 = Rectangle {
        width: dbg!(30 * scale),
        height: 50,
    };

    dbg!(&rect1);
}

我們可以把 dbg! 放在表達(dá)式 30 * scale 周?chē)?,因?yàn)?nbsp;dbg! 返回表達(dá)式的值的所有權(quán),所以 width 字段將獲得相同的值,就像我們?cè)谀抢餂](méi)有 dbg! 調(diào)用一樣。我們不希望 dbg! 擁有 rect1 的所有權(quán),所以我們?cè)谙乱淮握{(diào)用 dbg! 時(shí)傳遞一個(gè)引用。下面是這個(gè)例子的輸出結(jié)果:

$ cargo run
   Compiling rectangles v0.1.0 (file:///projects/rectangles)
    Finished dev [unoptimized + debuginfo] target(s) in 0.61s
     Running `target/debug/rectangles`
[src/main.rs:10] 30 * scale = 60
[src/main.rs:14] &rect1 = Rectangle {
    width: 60,
    height: 50,
}

我們可以看到第一點(diǎn)輸出來(lái)自 src/main.rs 第 10 行,我們正在調(diào)試表達(dá)式 30 * scale,其結(jié)果值是60(為整數(shù)實(shí)現(xiàn)的 Debug 格式化是只打印它們的值)。在 src/main.rs 第 14行 的 dbg! 調(diào)用輸出 &rect1 的值,即 Rectangle 結(jié)構(gòu)。這個(gè)輸出使用了更為易讀的 Debug 格式。當(dāng)你試圖弄清楚你的代碼在做什么時(shí),dbg! 宏可能真的很有幫助!

除了 Debug trait,Rust 還為我們提供了很多可以通過(guò) derive 屬性來(lái)使用的 trait,他們可以為我們的自定義類(lèi)型增加實(shí)用的行為。附錄 C 中列出了這些 trait 和行為。第十章會(huì)介紹如何通過(guò)自定義行為來(lái)實(shí)現(xiàn)這些 trait,同時(shí)還有如何創(chuàng)建你自己的 trait。除了 derive 之外,還有很多屬性;更多信息請(qǐng)參見(jiàn) Rust Reference 的 Attributes 部分。

我們的 area 函數(shù)是非常特殊的,它只計(jì)算長(zhǎng)方形的面積。如果這個(gè)行為與 Rectangle 結(jié)構(gòu)體再結(jié)合得更緊密一些就更好了,因?yàn)樗荒苡糜谄渌?lèi)型?,F(xiàn)在讓我們看看如何繼續(xù)重構(gòu)這些代碼,來(lái)將 area 函數(shù)協(xié)調(diào)進(jìn) Rectangle 類(lèi)型定義的 area 方法 中。


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

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)