- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试用 Rust 实现一个简单的分桶哈希表(仅供练习)。哈希表结构定义为:
pub struct BucketedHashTable<K: Hash, V> {
buckets: Vec<Bucket<K, V>>,
size: usize,
}
其中 Bucket
是我对单链接堆栈的简单实现。
在表的几乎所有方法中(put
、remove
、get
),我将获取关键所在的桶被插入(从中删除,在其中查找),所以我为此提取了一个方法:
fn pick_bucket(&mut self, key: K) -> &mut Bucket<K, V> {
let mut hasher = DefaultHasher::new();
key.hash(&mut hasher);
let hash = hasher.finish() as usize;
let index = hash % self.buckets.len();
&mut self.buckets[index]
}
我返回对桶的引用,因为我不想将它移出哈希表的 buckets
Vec。我返回一个可变引用,因为我将改变返回的存储桶(例如,在向其中插入一个新条目(键值对)时)。
以上代码编译通过。
但是如果我摆脱中间变量 index
并计算 []
括号内的索引,如下所示:
fn pick_bucket(&mut self, key: K) -> &mut Bucket<K, V> {
let mut hasher = DefaultHasher::new();
key.hash(&mut hasher);
let hash = hasher.finish() as usize;
&mut self.buckets[hash % self.buckets.len()]
}
我会得到这个借用错误:
error[E0502]: cannot borrow `self.buckets` as immutable because it is also borrowed as mutable
--> src\lib.rs:30:34
|
26 | fn pick_bucket(&mut self, key: K) -> &mut Bucket<K, V> {
| - let's call the lifetime of this reference `'1`
...
30 | &mut self.buckets[hash % self.buckets.len()]
| -------------------------^^^^^^^^^^^^^^^^^^-
| | | |
| | | immutable borrow occurs here
| | mutable borrow occurs here
| returning this value requires that `self.buckets` is borrowed for `'1`
我认为上面的两个代码片段是等价的。它们有何不同,为什么第一个可以编译,为什么第二个不能?
编辑: 我认为第一个代码片段中 self.buckets
的不可变借用超出了范围,并在行尾处“无效” let index = ...;
,所以当方法返回时,没有对 self.buckets
的共享引用;在第二个片段中,self.buckets
的不可变借用一直存在到方法返回(因此在那个时刻共享和可变引用共存)。如果这是正确的,为什么会这样?为什么 self.buckets
的不可变借用在第二种情况下到达 ]
括号时不会“失效”,而是在整个表达式(整个返回线)?
最佳答案
我相信您已经完全解决了您编辑中的问题。在第一个示例中,self.buckets
被不可变地借用,然后借用在语句末尾结束。在第二个示例中,self.buckets
被可变地借用,然后在同一语句中被不变地借用。这是不允许的。
self.buckets.len()
是临时的,它的生命周期规则(drop scope)在Temporary Scopes中解释。 :
Apart from lifetime extension, the temporary scope of an expression is the smallest scope that contains the expression and is one of the following:
- The entire function body.
- A statement.
- The body of a if, while or loop expression.
- The else block of an if expression.
- The condition expression of an if or while expression, or a match guard.
- The expression for a match arm.
- The second operand of a lazy boolean expression.
这在注释中有更进一步的解释:
Temporaries that are created in the final expression of a function body are dropped after any named variables bound in the function body, as there is no smaller enclosing temporary scope.
所以 self.buckets.len()
借用一直持续到函数结束(在函数体之后,甚至在语句完成之后)。但更容易将其视为持续到语句末尾(在任何情况下都会如此)。
没有在单个语句内创建的“子表达式”放置范围。理论上这可能是可能的,但 Rust 并没有那么激进。
关于rust - 借用中间变量可绕过的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70524766/
我正在使用 tcod-rs。用于绘制到 RootConsole 的每个方法都采用一个可变引用。中央循环是一个 while 循环,它等待窗口关闭、清除屏幕、绘制,然后刷新。 “检查窗口关闭”方法也采用可
This question already has answers here: How to return a reference to a sub-value of a value that is
我是新手,我已经阅读了有关所有权和借用的文档。显然,我开始为这个概念而苦苦挣扎... 这是我的代码: #[derive(Serialize, Deserialize, Debug)] pub stru
我在借阅检查器上遇到了问题。我有一个特征(Physics),它具有getters(例如velocity)和setters(例如velocity_mut)。它还具有使用getter和setter的默认方
我正在用 Rust 编写 Rogue-like。我有一个 Player,它有一个 Vec 的盒装 TimedEffects。定时效果有一个 activate(&mut Player) 和 deacti
我觉得 rc::Weak可以使用(某种)AsRef特征实现。我试图从弱指针借用一些共享内容,但这不会编译: use std::rc::Weak; struct Thing(Weak); impl Th
我正在学习Rust。对于我的第一个程序,我编写了以下代码来维护有关部分排序的数据: use std::collections::{HashMap, HashSet}; struct Node {
这个问题在这里已经有了答案: Cannot borrow as immutable because it is also borrowed as mutable in function argume
在尝试实现一个迭代器以产生对链表元素的可变引用时,我偶然发现了一个奇怪的问题。 这很好用: impl Iterator for LinkedListIterator{ fn next(&mut
我有this minimal example code : use std::borrow::BorrowMut; trait Foo {} struct Bar; impl Foo for Bar
struct State { x: i32 } trait A { fn a(&mut self, b: &i32); } impl A for State { fn a(&m
我有一个 Element 结构,它实现了一个更新方法,该方法需要一个滴答持续时间。该结构包含一个组件向量。允许这些组件在更新时修改元素。我在这里遇到借用错误,我不确定该怎么做。我尝试用 block 修
我正在尝试做这样的事情 use std::cell::{RefCell,Ref,RefMut}; use std::rc::Rc; struct Entity; struct Tile { e
我已连接到 Deribit websocket 以获取选项数据,但以下代码片段仅获得一个有效的数据响应,然后停止更新,但表示它仍在运行。 该网站建议使用 asyncio 模块,但能够使用以下代码片段提
我是一名优秀的程序员,十分优秀!