我正在创建一个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
Run Code Online (Sandbox Code Playgroud)
我的印象是,一个特征由两个指针组成,一个指向 vtable,一个指向对象数据。所以任何特征的大小,包括MyTrait,都应该是2 * pointer_size。此外,对象数据指针指向MyStruct大小已知的 a 。显然我的理解是错误的,但我不明白为什么。
这是我的代码:
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
}
}
Run Code Online (Sandbox Code Playgroud)
MyTrait当您在as中声明该方法时,这将创建一个按值而不是引用获取参数的fn my_fun(self);方法。在 Rust 中,大多数值都没有隐式克隆(对于那些有隐式克隆的值,它只支持直接的逐位复制)。self
一般来说,按值传递参数会导致它被移动,之后它的旧位置不再有效,并且以某种方式访问成为无效行为。(尽管编译器强制不会发生这种情况。)
该错误并不是说您不能Box<dyn MyTrait>在 a 的值中包含 a HashMap,而是说您不能将 a 移出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。顾名思义,这使得哈希映射中的值无法再访问。
| 归档时间: |
|
| 查看次数: |
1754 次 |
| 最近记录: |