给定以下代码:
trait Function {
fn filter (&self);
}
#[derive(Debug, Copy, Clone)]
struct Kidney {}
impl Function for Kidney {
fn filter (&self) {
println!("filtered");
}
}
fn main() {
let k = Kidney {};
let f: &Function = &k;
//let k1 = (*f); //--> This gives a "size not satisfied" error
(*f).filter(); //--> Works; what exactly happens here?
}
我不确定它为什么会编译。我原以为最后一条语句会失败。我想我在学习 Rust 时忽略了一些基础知识,因为我不明白为什么取消引用一个特征(存在于指针后面)应该编译。
这个问题是不是和下面的情况类似?
let v = vec![1, 2, 3, 4];
//let s: &[i32] = *v;
println!("{}", (*v)[0]);
*v
给出了一个切片,但是一个切片没有大小,所以我还是不清楚它是如何编译的。如果我取消注释我得到的第二条语句
| let s:&[i32]= *v;
| ^^
| |
| expected &[i32], found slice
| help: consider borrowing here: `&*v`
|
= note: expected type `&[i32]`
found type `[{integer}]`
expected type &[i32]
是否表示“预期的 slice 引用”?
最佳答案
解除对特征对象的引用是没有问题的。事实上,它必须在某个时候被取消引用,否则它会毫无用处。
let k1 = (*f);
失败不是因为取消引用,而是因为您试图将原始特征对象放在堆栈上(这是局部变量所在的位置)。堆栈上的值必须具有编译时已知的大小,特征对象不是这种情况,因为任何类型都可以实现该特征。
这是一个示例,其中具有不同大小的结构实现了特征:
trait Function {
fn filter (&self);
}
#[derive(Debug, Copy, Clone)]
struct Kidney {}
impl Function for Kidney {
fn filter (&self) {
println!("filtered");
}
}
#[derive(Debug, Copy, Clone)]
struct Liver {
size: f32
}
impl Function for Liver {
fn filter (&self) {
println!("filtered too!");
}
}
fn main() {
let k = Kidney {};
let l = Liver {size: 1.0};
let f: &Function;
if true {
f = &k;
} else {
f = &l;
}
// Now what is the size of *f - Kidney (0 bytes) or Liver (4 bytes)?
}
(*f).filter();
之所以有效,是因为临时取消引用的对象没有放在堆栈上。事实上,这与 f.filter()
是一样的。 Rust 会根据需要自动应用尽可能多的解引用以获取实际对象。这记录在案 in the book .
第二种情况发生的是 Vec
implements Deref
切片,因此它免费获得为切片实现的所有方法。 *v
为您提供一个取消引用的切片,您将其分配给一个切片。这是一个明显的类型错误。
关于rust - 为什么在取消引用的特征对象或切片上调用方法会编译?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49271585/