rust - dyn MyTrait的大小无法在采用self的方法中静态确定。

标签 rust

我正在创建HashMap<u64, Box<dyn MyTrait>>。我可以创建HashMap并插入一个实现MyTrait的结构,但是当我检索MyTrait并尝试使用它时,编译器向我提示:

error[E0161]: cannot move a value of type dyn MyTrait: the size of dyn MyTrait cannot be statically determined
我的印象是,特征包含两个指针,一个指向vtable,另一个指向对象数据。因此,包括MyTrait在内的任何特征的大小都应为2 * pointer_size。此外,对象数据指针指向大小已知的MyStruct。显然,我的理解是错误的,但我不知道为什么。
这是我的代码:
use std::collections::HashMap;

fn main() {
  let mut hm: HashMap<u64, Box<dyn MyTrait>> = HashMap::new();
  hm.insert(0, Box::new(MyStruct{num: 0}));
  match hm.get(&(0 as u64)) {
    Some(r) => {
      r.my_fun();
      }
    None => { println!("not found");}
  }
}

pub trait MyTrait {
  fn my_fun(self);
}

struct MyStruct {
  num: u64,
}

impl MyTrait for MyStruct {
  fn my_fun(self) {
    println!("num is {}", self.num);
    return
  }
}

最佳答案

当您在MyTrait中将方法声明为fn my_fun(self);时,这将创建一个通过值而不是通过引用使用self参数的方法。在Rust中,大多数值都没有隐式克隆(对于那些值,它仅支持逐位直接复制)。
通常,按值传递参数会导致其被移动,此后其旧位置不再有效,并且以某种方式变为无效行为。 (尽管这不会发生是由编译器强制执行的。)
错误并不是说您不能在Box<dyn MyTrait>的值中包含HashMap,而是您不能将dyn MyTrait&Box<dyn MyTrait>调用中获得的hm.get引用中移出。即使在那里有大小类型而不是无大小类型,这仍然是不可能的,因为除非类型为Copy,否则您不能将值从共享引用的后面移出。 (在这种情况下,它是完全复制而不是移动的。)
最有可能的是,您想使用fn my_fun(&self),它通过引用而不是值来接受self参数。
如果要更改函数中的值,则应声明函数fn my_fun(&mut self),然后将hm.get替换为hm.get_mut,以便您可以对MyStruct进行可变引用。
如果确实需要通过值而不是引用来获取self参数,则可以编写fn my_fun(self: Box<Self>)声明self参数是一个装箱的值,然后将hm.get行更改为hm.remove。顾名思义,这将使值不再在哈希图中可访问。

关于rust - dyn MyTrait的大小无法在采用self的方法中静态确定。,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63766721/

相关文章:

string - 如何在 Option<T> 中延长 T 的生命周期

rust - 将本地字符串作为切片返回 (&str)

generics - 集合中的扩展特征

linux - 错误 : "linker ' cc' not found"when cross compiling a rust project from windows to linux using cargo

arrays - 无法将迭代器转换为 js_sys::Array

path - 什么是连接任意数量的组件以在 Rust 中构建路径的宏?

由于库不纯导致的 Debian 9.2 错误

rust - 当值包含键和值之间的分隔符或对之间的分隔符时,如何从字符串中提取键和值?

rust - 取消引用原始指针的语义是什么?

string - Rust 是否提供了一种直接从字节 (u8) 数组中的 ASCII 数据解析整数的方法?