我有一个或多或少看起来像这样的程序
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);
}基本上,我们在struct Test上调用一个方法,该方法借用了一些值。然后,我们在相同的结构上调用另一个方法,传递先前获得的值。
这个例子非常好用。现在,当我们使main的内容变得通用时,它就不再起作用了。
fn generic_main<T>(t: Test<T>) {
let x = t.get_first();
t.do_something_with_x(*x);
}然后,我得到以下错误:
错误:不能移出借来的内容 src/main.rs:14设raw_x = *x;
我不太清楚为什么会发生这种事。有人能向我解释为什么Test<i32>在调用get_first时没有被借用,而Test<T>是借用的吗?
发布于 2015-02-18 23:16:51
简单地说,i32实现了Copy特性,但是T没有。如果您使用fn generic_main<T: Copy>(t: Test<T>),那么您当前的问题就解决了。
更长的答案是,Copy是一种特殊的特性,它意味着可以通过简单地复制位来复制值。像i32这样的类型实现Copy。像String这样的类型不实现Copy,因为例如,它需要堆分配。如果仅通过复制位来复制String,则最终将得到指向同一内存块的两个String值。那不太好(不安全!)
因此,给T一个Copy约束是非常有限制的。限制较小的限制将是T: Clone。Clone特性类似于Copy (在复制值方面),但它通常不仅仅是“复制位”。例如,String类型将通过为底层内存创建新的堆分配来实现Clone。
这要求您更改编写generic_main的方式:
fn generic_main<T: Clone>(t: Test<T>) {
let x = t.get_first();
t.do_something_with_x(x.clone());
}或者,如果您不希望具有Clone或Copy边界,则可以更改do_something_with_x方法以获取对T的引用,而不是对拥有的T的引用
impl<T> Test<T> {
// other methods elided
fn do_something_with_x(&self, x: &T) {
// Irrelevant
}
}而且你的generic_main基本上是一样的,除了你没有取消引用x
fn generic_main<T>(t: Test<T>) {
let x = t.get_first();
t.do_something_with_x(x);
}您可以阅读更多关于Copy 在医生里的内容。有一些很好的例子,包括如何为您自己的类型实现Copy。
https://stackoverflow.com/questions/28595075
复制相似问题