我在使用泛型型別創建簡單結構時遇到問題,如下所示:
struct Point3<T> {
pub x: T,
pub y: T,
pub z: T,
}
impl<T> Point3<T>
{
fn create3(vx: T, vy: T, vz: T) -> Point3<T> {
Point3::<T> {
x: vx,
y: vy,
z: vz,
}
}
fn create1(v: T) -> Point3<T> {
Point3::<T> {
x: v,
y: v,
z: v,
}
}
}
但是當我試圖編譯它時,我得到了一個錯誤:
fn create1(v: T) -> Point3<T> {
| - move occurs because `v` has type `T`, which does not implement the `Copy` trait
34 | Point3::<T> {
35 | x: v,
| - value moved here
36 | y: v,
| ^ value used here after move
我了解 thanv已搬入x,因此不適用于yor z。所以看來我需要復制它,但我不知道該怎么做,也沒有實作Copytrait forT因為它是泛型型別
如果我通過vref 我還有另一個錯誤
我敢肯定這很簡單,但是目前 ac/c dev rust 對我來說很復雜 :)
uj5u.com熱心網友回復:
當使用型別引數時,Rust 對型別的唯一假設是它是Sized. 必須明確寫出型別引數上的任何其他約束。
此外,Rust 的默認移動語意意味著一個值只能有一個所有者,并且一旦一個值“移出”一個地方,它就不再有效。您可以通過實作來選擇退出此行為Copy,盡管這僅對可以有意義地編輯的型別有效memcpy,所以很多東西不能使用它(任何帶有Dropimpl的東西&mut T,等等)。TLDR,它是一個相當嚴格的 API 系結。
更一般的情況是Clone,它是 的超特征Copy(這意味著:任何T實作Copy,也實作Clone)。不同之處在于這Clone可能是一項昂貴的操作,可能需要堆分配,并且必須通過顯式呼叫Clone::clone,但權衡是它的適用范圍更廣。
所以我建議重寫你的代碼如下:
// this function doesn't need to impose any special bounds on T,
// since it never needs to be cloned
impl<T> Point3<T> {
fn create3(x: T, y: T, z: T) -> Self {
Self { x, y, z }
}
}
// this function does require clone, so we have to add the bound
impl<T: Clone> Point3<T> {
fn create1(v: T) -> Self {
Self {
x: v.clone(),
y: v.clone(),
z: v,
}
}
}
這允許您的 API 被更多型別使用,但也不會增加型別的任何性能開銷Copy,因為型別的Clone實作Copy基本上也是一個標準的memcpy.
誠然,對于名為 的結構Point3,它可能只用于數字,因此CopyvsClone的區別不是很相關,但在一般情況下,Clone邊界更廣泛使用。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/435081.html
