我在某些Rust代码中遇到问题,在某些条件下(第一个令人困惑的部分)我被允许借用多次可变的东西,而不是其他东西。
我写了以下示例来说明: (Playground)
struct NoLifetime {}
struct WithLifetime <'a> {
pub field: &'a i32
}
fn main() {
let mut some_val = NoLifetime {};
borrow_mut_function(&mut some_val);
borrow_mut_function(&mut some_val); // Borrowing as mutable for the second time.
let num = 5;
let mut life_val = WithLifetime { field: &num };
borrow_lifetime(&mut life_val);
borrow_lifetime(&mut life_val); // Borrowing as mutable for the second time.
let num_again = borrow_lifetime(&mut life_val); // Borrow, assign lifetime result
borrow_lifetime(&mut life_val); // Compiler: cannot borrow `life_val` as mutable more than once
}
fn borrow_mut_function(val_in: &mut NoLifetime) -> String {
"abc".to_string()
}
fn borrow_lifetime<'a>(val_in: &'a mut WithLifetime) -> &'a i32 {
val_in.field
}
如果你看到,我可以多次借用some_val
和life_val
作为可变对象。但是,在分配borrow_lifetime
的返回值后,我再也无法借用。
我的问题如下:
borrow_
函数时,我都会将其作为可变对象。任何帮助将不胜感激。我想这里发生的事情是,我误解了什么是“可变的借款”。真的意味着,何时确定某些东西被借用为可变的。
答案 0 :(得分:7)
Chris already gave the gist of it,但我认为值得进一步解释。
在Rust中有 2 方式转让所有权:
Rust和许多其他语言一样,使用一堆词法范围模拟时间传递。结果,现在,借用从创建它开始并延伸到其范围的结尾。
因此,借款何时结束的问题类似于询问借款的创造范围。
让我们用带数字的行来回顾你的例子:
fn main() {
let mut some_val = NoLifetime {}; // 1
borrow_mut_function(&mut some_val); // 2
borrow_mut_function(&mut some_val); // 3
//
let num = 5; // 4
let mut life_val = WithLifetime { field: &num }; // 5
borrow_lifetime(&mut life_val); // 6
borrow_lifetime(&mut life_val); // 7
//
let num_again = borrow_lifetime(&mut life_val); // 8
borrow_lifetime(&mut life_val); // 9
}
调用函数时,借用参数:
所以,让我们来看看:
在第(2)和(3)行上调用borrow_mut_function
,返回String
:结果不与参数共享任何生命周期,因此参数仅用于函数调用的生命周期。
在第(6)和(7)行,你调用borrow_lifetime
返回一个&'a i32
:结果与参数共享一个生命周期,因此参数被借用直到结束结果的范围......由于未使用结果,因此立即生效。
在第(8)行,您调用borrow_lifetime
,返回&'a i32
,然后将结果分配给num_again
:结果共享一生使用参数,所以参数被借用到num_again
范围的末尾。
在第(9)行,你调用borrow_lifetime
但是它的参数仍由num_again
借用,所以这个电话是非法的。
就是这样,这就是Rust今天的工作方式。
将来需要non-lexical borrows。也就是说,编译器会意识到:
num_again
从未使用num_again
没有特定的析构函数(没有Drop
实现)答案 1 :(得分:5)
这是关于借款的范围,以及你是否保持借款。在上面的大多数调用中,some_val
在函数调用期间被借用,但在函数返回后返回。
在例外情况下:
let num_again = borrow_lifetime(&mut life_val); //Borrow, assign lifetime result
您在调用life_val
期间借用borrow_lifetime
,但由于返回值与参数('a
)具有相同的生命周期,因此借用范围将扩展为包括生命期为num_again
,即直到函数结束。再次借用life_val
是不安全的,因为num_again
仍然是对它的引用。