Nat*_*dge 6 hashmap rust interior-mutability
我有一个struct,称之为Book,比方说存储书店出售的一本书的数据。它需要在某些数据结构中的许多地方被引用(例如 with Rc),因此不能以正常方式可变地借用。然而,它有一些属性,比如它的价格,需要在初始化之后的某个时间填写,在对象已经有未完成的引用之后。
到目前为止,我可以想到两种方法来做到这一点,但它们都有缺点:
内部可变性:给出Book一个字段,例如 price: RefCell<Option<i32>>which 被初始化为RefCell::new(Option::None)whenBook被初始化。稍后,当我们确定书的价格时,我们可以使用borrow_mutto set pricetoSome(10)代替,然后我们可以使用borrow它来检索它的价值。
我的感觉是,一般来说,除非有必要,否则人们希望避免内部可变性,而且这里似乎没有那么必要。这种技术也有点尴尬,因为Option我们需要它,因为价格直到稍后才会有值(并且将其设置为0或-1同时看起来不像 Rustlike),但是它需要很多地方matches 或unwraps我们可以从逻辑上确定价格已经被填写。
单独的表:根本不将价格存储在里面Book,而是创建一个单独的数据结构来存储它,例如price_table: HashMap<Rc<Book>, i32>. 有一个函数,它在价格确定时创建并填充该表,然后通过引用(可变或不可变)将其传递给需要知道或更改书籍价格的每个函数。
像我一样来自 C 背景,HashMap感觉在速度和内存方面都是不必要的开销,因为数据已经有一个自然的地方(内部Book)并且“应该”通过一个简单的指针追逐来访问。这个解决方案还意味着我必须用一个引用price_table.
这两种方法中的一种在 Rust 中通常更惯用,还是有其他方法可以避免这种困境?我确实看到了Once,但我认为这不是我想要的,因为我仍然需要在初始化时知道如何填写price,而我不知道。
当然,在其他应用程序中,我们可能需要一些其他类型而不是i32表示我们想要的属性,所以我希望能够处理一般情况。
我认为您的第一种方法最适合这种情况。由于您对要写入的某些数据有未完成的引用,因此您必须在运行时检查借用规则,这RefCell就是要走的路。在 中RefCell,更喜欢 anOption或enum具有变体的自定义,如Price::NotSet和Price::Set(i32)。如果您确实确定所有价格都在某个时刻初始化,您可以编写一个方法price()来调用unwrap您或在您RefCell包含None.
我想这种HashMap方法对于这种情况来说是没问题的,但是如果你想要有一些不符合Copy你的价值的东西,你可能会遇到同样的问题,因为在地图的某个地方可能有未完成的引用。
我同意,即使作为值类型,这HashMap也不是这里的惯用方式,并且仍然选择您的第一种方法。i32
编辑:
正如评论中指出的(谢谢!),这种情况有两个性能考虑因素。首先,如果您确实知道所包含的价格永远不会为零,您可以免费使用std::num::NonZeroU16并获取该Option变体(请参阅文档)。None
如果您正在处理的类型是Copy(例如i32),您应该考虑使用Cell而不是RefCell,因为它更轻。更详细的比较请参见/sf/answers/2119330531/
| 归档时间: |
|
| 查看次数: |
80 次 |
| 最近记录: |