首页 > 解决方案 > 没有移动的 rust pass 框参考

问题描述

背景:

我正在用 rust 编写 RDBMS

db.catalog 维护一个从 table_id 到 table 的 hashmap:

pub struct Catalog {
    table_id_table_map: HashMap<i32, Box<dyn Table>>,
}

当我将盒装表添加到目录时,发生了移动。然后我不能再使用表实例了:

// create table
let table = create_random_heap_table(....);
// add to catalog
db.get_catalog().add_table(Box::new(table), "heap table", "");
// access table instance
let table_id = table.get_id();

编译错误:

error[E0382]: borrow of moved value: `table`
   --> src/lib.rs:113:32
    |
103 |                 let table = create_random_heap_table(
    |                     ----- move occurs because `table` has type `table::HeapTable`, which does not implement the `Copy` trait
...
111 |                 db.get_catalog().add_table(Box::new(table), "heap table", "");
    |                                                     ----- value moved here
112 | 
113 |                 let table_id = table.get_id();
    |                                ^^^^^ value borrowed here after move

标签: rustborrow-checker

解决方案


一旦您Catalog拥有该表的所有权,您就可以通过引用访问它。

如果您描述的用例很常见,也许您可​​以调整您的add_table方法以返回对刚刚添加的表的引用。

HashMap提供EntryAPI 作为符合人体工程学的方式来执行此操作 - 例如,您add_table可能看起来像这样:

fn add_table(&mut self, table: Box<dyn Table>/*, ... other arguments */) -> &mut Box<dyn Table> {

    let id = // figure out id somehow

    // Insert table into catalog and return a reference to it        
    self.table_id_table_map.entry(id).or_insert(table)
}

在那个简化的例子中,我没有考虑如果地图已经有一个给定的条目会发生什么id- 如果你的逻辑需要,你可以使用类似的模式来检查它。

现在你可以像这样使用它:

// create table
let table = create_random_heap_table(....);
// add to catalog
let table = db.get_catalog().add_table(Box::new(table), "heap table", "");
// access table instance
let table_id = table.get_id();

推荐阅读