簡體   English   中英

Rust 是否會擦除泛型類型?

[英]Does Rust erase generic types or not?

Rust 中是否存在泛型類型擦除(如 Java)? 我無法找到明確的答案。

當您使用泛型函數或泛型類型時,編譯器會為每個不同的類型參數集生成一個單獨的實例(我相信生命周期參數會被忽略,因為它們對生成的代碼沒有影響)。 這個過程稱為單態化 例如, Vec<i32>Vec<String>是不同的類型,因此Vec<i32>::len()Vec<String>::len()是不同的函數。 這是必要的,因為Vec<i32>Vec<String>具有不同的內存布局,因此需要不同的機器碼! 因此,,沒有類型擦除。

如果我們使用Any::type_id() ,如下例所示:

use std::any::Any;

fn main() {
    let v1: Vec<i32> = Vec::new();
    let v2: Vec<String> = Vec::new();
    
    let a1 = &v1 as &dyn Any;
    let a2 = &v2 as &dyn Any;
    
    println!("{:?}", a1.type_id());
    println!("{:?}", a2.type_id());
}

我們為Vec兩個實例獲得不同的類型 ID。 這支持Vec<i32>Vec<String>是不同類型的事實。

然而,Rust 中的反射能力是有限的; Any幾乎就是我們現在所擁有的。 您無法獲得有關運行時值類型的更多信息,例如其名稱或其成員。 為了能夠使用Any ,您必須將其Any::downcast_ref()使用Any::downcast_ref()Any::downcast_mut()為編譯時已知的類型。

Rust 確實通過dyn Trait以虛方法分派的形式進行類型擦除,這允許您擁有一個Vec ,其中元素具有不同的具體類型:

fn main() {
    let list: Vec<Box<dyn ToString>> = vec![Box::new(1), Box::new("hello")];

    for item in list {
        println!("{}", item.to_string());
    }
}

(操場)

請注意,編譯器要求您手動裝箱元素,因為它必須在編譯時知道每個值的大小。 您可以使用Box ,無論它指向什么,它都具有相同的大小,因為它只是一個指向堆的指針。 您還可以使用& -references:

fn main() {
    let list: Vec<&dyn ToString> = vec![&1, &"hello"];

    for item in list {
        println!("{}", item.to_string());
    }
}

(操場)

但是,請注意,如果您使用& -references,您可能會遇到生命周期問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM