鍍金池/ 教程/ Java/ 結(jié)構(gòu)體
哲學(xué)家就餐問題
鏈接進(jìn)階
名詞中英文對照
測試
引用和借用
泛型
方法語法
函數(shù)
不安全代碼
并發(fā)
裝箱語法和模式
注釋
棧和堆
運(yùn)算符與重載
語法索引
文檔
固有功能
所有權(quán)
循環(huán)
通用函數(shù)調(diào)用語法
不定長類型
<code>const</code> 和 <code>static</code>
迭代器
其他語言中的 Rust
枚舉
詞匯表
If語句
猜猜看
錯誤處理
生命周期
編譯器插件
發(fā)布途徑
閉包
trait 對象
不使用標(biāo)準(zhǔn)庫
關(guān)聯(lián)常量
外部函數(shù)接口(FFI)
類型轉(zhuǎn)換
原生類型
匹配
參考文獻(xiàn)
Rust 編程語言
內(nèi)聯(lián)匯編
條件編譯
選擇你的保證
學(xué)習(xí) Rust
`type`別名
自定義內(nèi)存分配器
屬性
if let
高效 Rust
可變性
語法和語義
模式
基準(zhǔn)測試
結(jié)構(gòu)體
變量綁定
語言項(xiàng)
切片模式
<code>Deref</code> 強(qiáng)制多態(tài)
關(guān)聯(lián)類型
裸指針
<code>Borrow</code> 和 <code>AsRef</code>
準(zhǔn)備
Rust 開發(fā)版
字符串

結(jié)構(gòu)體

structs.md
commit 6ba952020fbc91bad64be1ea0650bfba52e6aab4

結(jié)構(gòu)體是一個創(chuàng)建更復(fù)雜數(shù)據(jù)類型的方法。例如,如果我們正在進(jìn)行涉及到 2D 空間坐標(biāo)的計(jì)算,我們將需要一個x和一個y值:

let origin_x = 0;
let origin_y = 0;

結(jié)構(gòu)體讓我們組合它們倆為一個單獨(dú),統(tǒng)一的數(shù)據(jù)類型:

struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let origin = Point { x: 0, y: 0 }; // origin: Point

    println!("The origin is at ({}, {})", origin.x, origin.y);
}

這里有許多細(xì)節(jié),讓我們分開說。我們使用了struct關(guān)鍵字后跟名字來定義了一個結(jié)構(gòu)體。根據(jù)傳統(tǒng),結(jié)構(gòu)體使用大寫字母開頭并且使用駝峰命名法:PointInSpace而不要寫成Point_In_Space。

像往常一樣我們用let創(chuàng)建了一個結(jié)構(gòu)體的實(shí)例,不過我們用key: value語法設(shè)置了每個字段。這里順序不必和聲明的時候一致。

最后,因?yàn)槊總€字段都有名字,我們可以訪問字段通過圓點(diǎn)記法:origin.x。

結(jié)構(gòu)體中的值默認(rèn)是不可變的,就像 Rust 中其它的綁定一樣。使用mut使其可變:

struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let mut point = Point { x: 0, y: 0 };

    point.x = 5;

    println!("The point is at ({}, {})", point.x, point.y);
}

上面的代碼會打印The point is at (5, 0)

Rust 在語言級別不支持字段可變性,所以你不能像這么寫:

struct Point {
    mut x: i32,
    y: i32,
}

可變性是綁定的一個屬性,不是結(jié)構(gòu)體自身的。如果你習(xí)慣于字段級別的可變性,這開始可能看起來有點(diǎn)奇怪,不過這樣明顯地簡化了問題。它甚至可以讓你使變量只可變一段臨時時間:

struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let mut point = Point { x: 0, y: 0 };

    point.x = 5;

    let point = point; // now immutable

    point.y = 6; // this causes an error
}

你的結(jié)構(gòu)體仍然可以包含&mut指針,它會給你一些類型的可變性:

struct Point {
    x: i32,
    y: i32,
}

struct PointRef<'a> {
    x: &'a mut i32,
    y: &'a mut i32,
}

fn main() {
    let mut point = Point { x: 0, y: 0 };

    {
        let r = PointRef { x: &mut point.x, y: &mut point.y };

        *r.x = 5;
        *r.y = 6;
    }

    assert_eq!(5, point.x);
    assert_eq!(6, point.y);
}

更新語法(Update syntax)

一個包含..struct表明你想要使用一些其它結(jié)構(gòu)體的拷貝的一些值。例如:

struct Point3d {
    x: i32,
    y: i32,
    z: i32,
}

let mut point = Point3d { x: 0, y: 0, z: 0 };
point = Point3d { y: 1, .. point };

這給了point一個新的y,不過保留了xz的值。這也并不必要是同樣的struct,你可以在創(chuàng)建新結(jié)構(gòu)體時使用這個語法,并會拷貝你未指定的值:

# struct Point3d {
#     x: i32,
#     y: i32,
#     z: i32,
# }
let origin = Point3d { x: 0, y: 0, z: 0 };
let point = Point3d { z: 1, x: 2, .. origin };

元組結(jié)構(gòu)體

Rust有像另一個[元組](Primitive Types 原生類型.md#tuples)和結(jié)構(gòu)體的混合體的數(shù)據(jù)類型。元組結(jié)構(gòu)體有一個名字,不過它的字段沒有。他們用struct關(guān)鍵字聲明,并元組前面帶有一個名字:

struct Color(i32, i32, i32);
struct Point(i32, i32, i32);

let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);

這里blackorigin并不相等,即使它們有一模一樣的值:

let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);

使用結(jié)構(gòu)體幾乎總是好于使用元組結(jié)構(gòu)體。我們可以這樣重寫ColorPoint

struct Color {
    red: i32,
    blue: i32,
    green: i32,
}

struct Point {
    x: i32,
    y: i32,
    z: i32,
}

現(xiàn)在,我們有了名字,而不是位置。好的名字是很重要的,使用結(jié)構(gòu)體,我們就可以設(shè)置名字。

不過有種情況元組結(jié)構(gòu)體非常有用,就是當(dāng)元組結(jié)構(gòu)體只有一個元素時。我們管它叫新類型newtype),因?yàn)槟銊?chuàng)建了一個與元素相似的類型:

struct Inches(i32);

let length = Inches(10);

let Inches(integer_length) = length;
println!("length is {} inches", integer_length);

如你所見,你可以通過一個解構(gòu)let來提取內(nèi)部的整型,就像我們在講元組時說的那樣,let Inches(integer_length)integer_length賦值為10。

類單元結(jié)構(gòu)體(Unit-like structs)

你可以定義一個沒有任何成員的結(jié)構(gòu)體:

struct Electron;

let x = Electron;

這樣的結(jié)構(gòu)體叫做“類單元”因?yàn)樗c一個空元組類似,(),這有時叫做“單元”。就像一個元組結(jié)構(gòu)體,它定義了一個新類型。

就它本身來看沒什么用(雖然有時它可以作為一個標(biāo)記類型),不過在與其它功能的結(jié)合中,它可以變得有用。例如,一個庫可能請求你創(chuàng)建一個實(shí)現(xiàn)了一個特定特性的結(jié)構(gòu)來處理事件。如果你并不需要在結(jié)構(gòu)中存儲任何數(shù)據(jù),你可以僅僅創(chuàng)建一個類單元結(jié)構(gòu)體。