我目前正在学习Rust中的闭包,并试图理解为什么它们会一直持有引用,直到最后一次使用.

请考虑以下代码:

fn borrows_mutably_func(list: &mut Vec<i32>) {
    list.push(4);
}

fn main() {
    let mut list = vec![1, 2, 3];
    println!("Before defining: {:?}", list);


    borrows_mutably_func(&mut list);
    println!("After calling first (func): {:?}", list);
    borrows_mutably_func(&mut list);
    println!("After calling second (func): {:?}", list);
    
    
    let mut borrows_mutably_closure = || list.push(5);
    
    borrows_mutably_closure();
    println!("After calling first (closure): {:?}", list);
    borrows_mutably_closure();
    println!("After calling second (closure): {:?}", list);
}

在这段代码中,borrows_mutably_func是通过向list添加元素来改变list的函数.此函数可以多次调用,不会出现任何问题.然而,当我try 使用闭包(borrows_mutably_closure)复制此行为时,代码无法编译.

根据我的理解,之所以会出现这个问题,是因为闭包通过一个可变的引用捕获了list,并不断地保持这个引用,直到它最后一次使用.这与函数不同,后者在每次调用后释放引用.

我的问题是:为什么Rust要对闭包执行此行为?为什么闭包不能在第一次使用后释放可变引用(就像函数一样),并在第二次使用之前重新获取它?这种方法对我来说似乎更直观,因为它将允许闭包的行为类似于函数,而不需要连续持有可变引用.如有真知灼见,不胜感激!

推荐答案

我的问题是:为什么Rust要对闭包执行此行为?为什么闭包不能在第一次使用后释放可变引用(就像函数一样),并在第二次使用之前重新获取它?

因为这是不可行的.从本质上讲,闭合是一种 struct ,它存储了它关闭的所有东西.因此,在这里的第13行,您实际上实例化了一个类似以下内容的 struct :

struct BorrowsMutablyClosure<'a> {
    list: &'a mut Vec<i32> 
}
impl BorrowsMutablyClosure<'_> {
    fn call_mut(&mut self) {
        self.list.push(5);
    }
}

函数是一个完全不同的情况,你在每次调用过程中pass in次引用,这就是引用对函数可用的方式.

您可以对闭包做完全相同的事情,如果您将引用作为参数传递,它将不需要在内部存储引用.

对我来说,这种方法似乎更直观

但这毫无意义.从创建闭包的瞬间到销毁闭包的瞬间,可变引用必然是未完成的,因为闭包需要存储它.闭包不存在释放然后重新获取可变引用的机制.

Rust相关问答推荐

在HashMap中插入Vacant条目的可变借位问题

PyReadonlyArray2到Vec T<>

亚性状上位性状上的 rust 病伴生型界限

MPSC频道在接收器处阻塞

在跨平台应用程序中使用std::OS::Linux和std::OS::Windows

在Rust中是否可以使用Rc自动化约束传播

取得本地对象字段的所有权

是否可以使用Rust宏来构建元组的项?

为什么我们需要std::thread::scope,如果我们可以使用thread.join()在函数的生命周期内删除引用?

从未排序的链表中删除重复项的铁 rust 代码在ELSE分支的低级上做了什么?

在Rust 中移动原始指针的靶子安全吗

返回迭代器考虑静态生命周期类型

从光标位置旋转精灵

Rust 生命周期:这两种类型声明为不同的生命周期

bcrypt 有长度限制吗?

在运行时在 Rust 中加载字体

用逗号分隔字符串,但在标记中使用逗号

在 Rust 中退出进程

在 Traits 函数中设置生命周期的问题

如何创建动态创建值并向它们返回borrow 的工厂?