簡體   English   中英

為什么不能為通用選項克隆 None<t> 當 T 不實現克隆?</t>

[英]Why can't None be cloned for a generic Option<T> when T doesn't implement Clone?

給定一個帶有泛型Option<T>的結構,其中T可能無法實現Clone為什么不能克隆None T類型的None與其他任何None一樣嗎? 例如:

struct Foo<T> {
    bar: Vec<Option<T>>,
}

impl <T> Foo<T> {
    fn blank(size: usize) -> Foo<T> {
        Foo {
            bar: vec![None; size],
        }
    }
}

正如其他答案正確指出的那樣,這是由於vec! -宏已實施。 您可以手動創建任何Option<T>Vec ,而無需將T設為Clone

let bar = std::iter::repeat_with(|| Option::<T>::None).take(size).collect::<Vec<_>>();

這將創建size -number of Option::<T>::None並將它們放在Vec中,這將被預先分配到適當的大小。 這適用於任何T

如果一個部分不能被克隆,那么任何部分都不能被克隆。 從類型的角度考慮這一點:您有一個名為fooOption<T>類型的變量,其中T不可克隆。 當然, None可以被克隆,但Some(_)不能,並且變量的類型不會告訴你它是什么。 因此,從編譯時的角度來看,您無法克隆該選項。

T類型的None與其他任何None一樣嗎?

絕對不是,與 null 通常實現為空引用的基於引用的語言不同,Rust 的Option<T>不引入間接方法,並且在選項為Some時將T內聯存儲。 由於所有枚舉變體具有相同的大小,因此None變體仍必須至少占用與T一樣多的空間。

話雖如此,從技術上講,可以在沒有TClone的情況下克隆None值是正確的,因為枚舉的None變體包含T ,它只存儲鑒別器並保留可能包含T的空間,如果變體是更改為Some 但由於 Rust 枚舉變體不是單獨的類型,因此為枚舉定義的特征綁定必須涵蓋所有變體。

請參閱其他答案更詳細的解釋和說明如何創建不可克隆OptionNone值的向量。

Option只能在內部T實現Clone時被克隆:

impl<T> Clone for Option<T>
where
    T: Clone, 

T類型的None與其他任何None一樣嗎?

實際上,沒有。 Rust 編譯器甚至不將None視為一種類型。 相反, None只是Option<T>的變體(子類型)。 嘗試比較兩個不同TNone

let a: Option<String> = None;
let b: Option<u8> = None;

assert_eq!(a, b)

你會看到它們實際上是完全不相關的類型:

error[E0308]: mismatched types
 --> src/main.rs:4:5
  |
4 |     assert_eq!(a, b)
  |     ^^^^^^^^^^^^^^^^ expected struct `String`, found `u8`
  |
  = note: expected enum `Option<String>`
             found enum `Option<u8>`

所以 Rust 編譯器實際上將None視為Option::<T>::None 這意味着如果T不是Clone ,則Option<T>不是Clone ,因此Option::<T>::None不能是Clone

要使您的代碼編譯,您必須將T限制為Clone

struct Foo<T: Clone> {
    bar: Vec<Option<T>>,
}

impl <T: Clone> Foo<T> {
    fn blank(size: usize) -> Foo<T> {
        Foo {
            bar: vec![None; size],
        }
    }
}

現在編譯器知道TClone ,並且實現了Option<T> (和Option::<T>::None )的Clone實現。

暫無
暫無

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

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