本文簡要介紹rust語言中 Trait std::marker::Copy
的用法。
用法
pub trait Copy: Clone { }
可以簡單地通過複製位來複製其值的類型。
默認情況下,變量綁定有 'move semantics.' 換句話說:
#[derive(Debug)]
struct Foo;
let x = Foo;
let y = x;
// `x` has moved into `y`, and so cannot be used
// println!("{:?}", x); // error: use of moved value
但是,如果一個類型實現了 Copy
,則它改為具有 'copy semantics':
// We can derive a `Copy` implementation. `Clone` is also required, as it's
// a supertrait of `Copy`.
#[derive(Debug, Copy, Clone)]
struct Foo;
let x = Foo;
let y = x;
// `y` is a copy of `x`
println!("{:?}", x); // A-OK!
需要注意的是,在這兩個示例中,唯一的區別是是否允許您在分配後訪問x
。在幕後,複製和移動都可能導致位被複製到內存中,盡管有時這會被優化掉。
如何實現 Copy
?
有兩種方法可以在您的類型上實現Copy
。最簡單的是使用 derive
:
#[derive(Copy, Clone)]
struct MyStruct;
您還可以手動實現Copy
和Clone
:
struct MyStruct;
impl Copy for MyStruct { }
impl Clone for MyStruct {
fn clone(&self) -> MyStruct {
*self
}
}
兩者之間有一個小小的區別:derive
策略還將在類型參數上放置 Copy
綁定,但這並不總是需要的。
Copy
和 Clone
有什麽區別?
複製是隱式發生的,例如作為分配 y = x
的一部分。 Copy
的行為不可重載;它總是一個簡單的按位複製。
克隆是一個顯式操作,x.clone()
。 Clone
的實現可以提供安全複製值所需的任何 type-specific 行為。例如 String
的 Clone
的實現需要複製堆中指向的字符串緩衝區。 String
值的簡單按位複製隻會複製指針,從而導致雙倍釋放。因此, String
是 Clone
但不是 Copy
。
Clone
是 Copy
的超特征,因此 Copy
的所有內容也必須實現 Clone
。如果一個類型是Copy
,那麽它的 Clone
實現隻需要返回*self
(見上麵的例子)。
我的類型什麽時候可以是 Copy
?
如果一個類型的所有組件都實現了Copy
,則該類型可以實現Copy
。例如,這個結構可以是 Copy
:
#[derive(Copy, Clone)]
struct Point {
x: i32,
y: i32,
}
結構可以是 Copy
,而 i32
是 Copy
,因此 Point
有資格成為 Copy
。相比之下,考慮
struct PointList {
points: Vec<Point>,
}
結構 PointList
無法實現 Copy
,因為 Vec<T>
不是 Copy
。如果我們嘗試派生 Copy
實現,我們會得到一個錯誤:
the trait `Copy` may not be implemented for this type; field `points` does not implement `Copy`
共享參考 (&T
) 也是Copy
, 所以一個類型可以是Copy
,即使它擁有類型的共享引用T
那是不是 Copy
.考慮以下結構,它可以實現Copy
, 因為它隻持有一個共享參考對我們的非Copy
類型PointList
從上麵:
#[derive(Copy, Clone)]
struct PointListWrapper<'a> {
point_list_ref: &'a PointList,
}
什麽時候不能我的類型是Copy
?
某些類型無法安全複製。例如,複製 &mut T
將創建一個別名可變引用。複製 String
將重複管理 String
緩衝區的責任,從而導致雙重釋放。
概括後一種情況,任何實現 Drop
的類型都不能是 Copy
,因為它除了自己的 size_of::<T>
字節之外還管理一些資源。
如果您嘗試在包含非 Copy
數據的結構或枚舉上實現 Copy
,您將收到錯誤 E0204 。
什麽時候應該我的類型是Copy
?
一般來說,如果您的類型能夠實施Copy
, 它應該。但請記住,實施Copy
是您的類型的公共 API 的一部分。如果該類型可能變為非Copy
將來,謹慎的做法可能是省略Copy
現在實施,以避免重大 API 更改。
其他實現者
除了下麵列出的實現者之外,以下類型還實現 Copy
:
- 函數項類型(即為每個函數定義的不同類型)
- 函數指針類型(例如,
fn() -> i32
) - 元組類型,如果每個組件也實現
Copy
(例如,()
,(i32, bool)
) - 閉包類型,如果它們沒有從環境中捕獲任何值,或者所有這些捕獲的值都實現了
Copy
。請注意,共享引用捕獲的變量始終實現Copy
(即使引用對象沒有),而可變引用捕獲的變量從不實現Copy
。
外來類型的實現
相關用法
- Rust Copy用法及代碼示例
- Rust Condvar.notify_all用法及代碼示例
- Rust Command.args用法及代碼示例
- Rust Condvar.wait用法及代碼示例
- Rust Cow.is_owned用法及代碼示例
- Rust Cow用法及代碼示例
- Rust Condvar.wait_timeout用法及代碼示例
- Rust Condvar.wait_timeout_while用法及代碼示例
- Rust Command.env用法及代碼示例
- Rust Command.env_remove用法及代碼示例
- Rust Command.get_args用法及代碼示例
- Rust Command.stdout用法及代碼示例
- Rust Command.stdin用法及代碼示例
- Rust Components用法及代碼示例
- Rust Component.as_os_str用法及代碼示例
- Rust ControlFlow用法及代碼示例
- Rust Command.current_dir用法及代碼示例
- Rust Command.output用法及代碼示例
- Rust ControlFlow.break_value用法及代碼示例
- Rust Command.status用法及代碼示例
- Rust Cow.into_owned用法及代碼示例
- Rust Condvar.wait_while用法及代碼示例
- Rust Command.envs用法及代碼示例
- Rust Command用法及代碼示例
- Rust Command.get_program用法及代碼示例
注:本文由純淨天空篩選整理自rust-lang.org大神的英文原創作品 Trait std::marker::Copy。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。