Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Pointers 借用泛型类型时无法移出借用的内容_Pointers_Rust - Fatal编程技术网

Pointers 借用泛型类型时无法移出借用的内容

Pointers 借用泛型类型时无法移出借用的内容,pointers,rust,Pointers,Rust,我有一个程序或多或少是这样的 struct Test<T> { vec: Vec<T> } impl<T> Test<T> { fn get_first(&self) -> &T { &self.vec[0] } fn do_something_with_x(&self, x: T) { // Irrelevant } } fn ma

我有一个程序或多或少是这样的

struct Test<T> {
    vec: Vec<T>
}

impl<T> Test<T> {
    fn get_first(&self) -> &T {
        &self.vec[0]
    }

    fn do_something_with_x(&self, x: T) {
        // Irrelevant
    }
}

fn main() {
    let t = Test { vec: vec![1i32, 2, 3] };
    let x = t.get_first();
    t.do_something_with_x(*x);
}
然后我得到以下错误:

错误:无法移出借用的内容

src/main.rs:14让raw_x=*x


我不完全清楚为什么会发生这种情况。有人能解释一下为什么调用
get\u first
时没有借用
Test
,而
Test
是借用的吗?

简而言之,
i32
实现了
Copy
特性,但
t
没有。如果您使用
fn generic\u main(t:Test)
,那么您眼前的问题已经解决

较长的答案是,
Copy
是一种特殊的特性,这意味着可以通过简单地复制位来复制值。像
i32
这样的类型实现
Copy
。像
String
这样的类型不实现
Copy
,因为,例如,它需要堆分配。如果仅通过复制位来复制一个
字符串
,则会得到指向同一内存块的两个
字符串
值。那不太好(不安全!)

因此,给你的
T
一个
Copy
绑定是相当严格的。限制性较小的边界是
T:Clone
Clone
特性类似于
Copy
(它复制值),但它通常不仅仅通过“复制位”来完成。例如,
String
类型将通过为底层内存创建新的堆分配来实现
Clone

这要求您更改
generic\u main
的编写方式:

fn generic_main<T: Clone>(t: Test<T>) {
    let x = t.get_first();
    t.do_something_with_x(x.clone());
}
您的
generic\u main
基本保持不变,只是没有取消引用
x

fn generic_main<T>(t: Test<T>) {
    let x = t.get_first();
    t.do_something_with_x(x);
}
fn通用_main(t:测试){
设x=t,先得到_();
t、 用x(x)做某事;
}

您可以阅读有关
复制的更多信息。这里有一些很好的例子,包括如何为您自己的类型实现
Copy

使用“移动位”有点令人困惑,因为锈会随着移动位移动。也许“复制比特”会更清晰?@MatthieuM。当然更新。值得一提的是,我直接从语言参考中引用了前面的措辞:“复制,用于“普通的旧数据”类型,可以通过简单地移动位来复制。”@BurntSushi5:有趣的是,也许我们应该警告steve,在“复制”的上下文中使用“移动”有点混乱?
impl<T> Test<T> {
    // other methods elided

    fn do_something_with_x(&self, x: &T) {
        // Irrelevant
    }
}
fn generic_main<T>(t: Test<T>) {
    let x = t.get_first();
    t.do_something_with_x(x);
}