概念
Sized是Rust編譯階段檢查對(duì)象操作的一個(gè)基本依據(jù)筐付,Rust只允許操作已知大小的對(duì)象, 未知大小的對(duì)象只能操作它的指針(&)胁孙。
默認(rèn)情況下笔横,任何類型參數(shù)都是Sized限定的康辑,即:
<T> 等價(jià)于 <T: Sized>
在Rust里铃芦,如果一個(gè)類型的字節(jié)大小在編譯期可以確定,那么這個(gè)類型就是確定大小(Sized)的煤蚌。確定類型的大小(size)對(duì)于能夠在棧(stack)上為實(shí)例分配足夠的空間是十分重要的端三。確定大小類型(sized type)可以通過(guò)傳值(by value)或者傳引用(by reference)的方式來(lái)傳遞舷礼。
如果一個(gè)類型的大小不能在編譯期確定,那么它就被稱為不確定大小類型(unsized type)或者DST郊闯,即動(dòng)態(tài)大小類型(Dynamically-Sized Type)妻献。因?yàn)椴淮_定大小類型(unsized type)不能存放在棧上,所以它們只能通過(guò)傳引用(by reference)的方式來(lái)傳遞团赁。
示例代碼
以下代碼是正確的:
fn sized_correct() {
#[derive(Debug)]
struct Water<T>(T); // 等同于 struct Status<T: Sized>(T);
#[derive(Debug)]
struct Cup(Water<i32>);
let water = Water(10);
let cup = Cup(water);
println!("{:?}", cup); // output: Cup(Water(10))
}
以下代碼是錯(cuò)誤的:
fn sized_error() {
#[derive(Debug)]
struct Water<T>(T); // 等同于 struct Status<T: Sized>(T);
#[derive(Debug)]
struct Cup(Water<[i32]>); // 由于[i32] 是一個(gè)隊(duì)列, 因此它是未知大小
}
為了支持參數(shù)長(zhǎng)度可變育拨,需要進(jìn)行調(diào)整:
fn use_unsized_to_fix_sized_error() {
#[derive(Debug)]
#[allow(dead_code)]
struct Bar<T: ?Sized>(T);
#[derive(Debug)]
#[allow(dead_code)]
struct BarUse<'a>(Bar<&'a [i32]>);
}
盡管[i32]是可變長(zhǎng)度變量,但是&[i32]是一個(gè)指針欢摄,長(zhǎng)度是固定的熬丧,在加入?Sized
約束后,Bar
中使用到的范型可以是可變長(zhǎng)度變量怀挠。
在Rust中析蝴,指向數(shù)組的動(dòng)態(tài)大小視圖(dynamically sized views)被稱為切片(slice)。例如唆香,一個(gè)&str是一個(gè)"字符串切片(string slice)" 嫌变,一個(gè)&[i32]是一個(gè)"i32切片"。切片(slice)是雙寬度(double-width)的躬它,因?yàn)樗麄兇鎯?chǔ)了一個(gè)指向數(shù)組的指針和數(shù)組中元素的數(shù)量腾啥。
trait對(duì)象指針是雙寬度(double-width)的,因?yàn)樗麄兇鎯?chǔ)了一個(gè)指向數(shù)據(jù)的指針和一個(gè)指向vtable的指針冯吓。
不確定大小(unsized) 結(jié)構(gòu)體指針是雙寬度的倘待,因?yàn)樗麄兇鎯?chǔ)了一個(gè)指向結(jié)構(gòu)體數(shù)據(jù)的指針和結(jié)構(gòu)體的大小(size)。不確定大小(unsized) 結(jié)構(gòu)體只能擁有有1個(gè)不確定大小(unsized)字段(field)而且它必須是結(jié)構(gòu)體里的最后一個(gè)字段(field)组贺。
總結(jié)
只有確定大小類型(sized type)的實(shí)例可以被放到棧上凸舵,也就是,可以通過(guò)值傳遞失尖。
不確定大小類型(unsized type)的實(shí)例不能被放置在棧上并且必須通過(guò)引用來(lái)傳遞啊奄。
不確定大小類型(unsized type)的指針是雙寬度(double-width)的渐苏,因?yàn)槌酥赶驍?shù)據(jù)之外,他們還需要做一些額外的記錄來(lái)追蹤數(shù)據(jù)的長(zhǎng)度或者指向一個(gè)vtable菇夸。