rust - 为什么在取消引用的特征对象或切片上调用方法会编译?

标签 rust traits dereference

给定以下代码:

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/

相关文章:

rust - 将 (T, ()) 转换为 T 安全吗?

rust - 未解析的名称 rand::thread_rng

rust - 如何为 `Vec<i8>` 和 `&[i8]` 制作可索引包装器?

取消引用 "this"关键字的 C++ 结果

rust - 对存储在向量中的值的引用的生命周期

random - 特征界限不满足库中的错误

php - 如何使用 PHP7 从静态方法调用特征的非静态方法?

c - 当我向后浏览字符串时,为什么会在字符串开头遇到 NULL 终止字符?

c++ - 返回堆栈中的值 - C++

rust - 为什么在使用非文字模式时无法访问此匹配模式?