You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何在Rust中使用闭包时会出现值被借用的错误?

Rust闭包的借用错误解析与修复

错误原因

你遇到的问题核心是闭包的默认捕获方式和Rust的借用规则冲突:

  • Rust闭包会自动选择最小权限的捕获策略,这里闭包仅读取outer_var,所以默认捕获它的不可变引用,而非所有权或可变引用。
  • 闭包closure_annotated创建后,会持有outer_var的不可变引用,直到闭包被销毁。此时你尝试执行outer_var *= 100,需要获取outer_var的可变引用——这违反了Rust的借用规则:同一时间不能同时存在不可变引用和可变引用。
  • 变量存在栈内存不影响借用规则,Rust的借用检查是针对引用本身,和变量存储位置无关,只要涉及引用就必须遵守规则。

解决方案

根据你的需求,有几种可行的修复方式:

1. 让闭包捕获所有权(不再使用原变量)

如果后续不需要操作outer_var,可以用move关键字将outer_var的所有权转移给闭包:

fn main() {
    let mut outer_var = 42;

    let closure_annotated = move |i: i32| -> i32 { i + outer_var };
    println!("closure_annotated: {}", closure_annotated(1));
    // 注意:此处无法再使用outer_var,所有权已转移给闭包
    // outer_var *= 100; // 编译报错
    println!("closure_annotated2: {}", closure_annotated(1));
}

2. 拆分闭包生命周期(保留原变量使用)

如果需要先调用闭包、修改变量、再调用闭包,可以将第一个闭包限制在代码块中,销毁后释放引用:

fn main() {
    let mut outer_var = 42;

    {
        let closure_annotated = |i: i32| -> i32 { i + outer_var };
        println!("closure_annotated: {}", closure_annotated(1));
    } // 闭包在此销毁,引用释放
    outer_var *= 100;
    let closure_annotated2 = |i: i32| -> i32 { i + outer_var };
    println!("closure_annotated2: {}", closure_annotated2(1));
}

3. 使用内部可变性(闭包持有引用时修改变量)

如果需要闭包持续持有引用,同时修改原变量,可以用Cell(适用于Copy类型如i32)实现内部可变性:

use std::cell::Cell;

fn main() {
    let outer_var = Cell::new(42);

    let closure_annotated = |i: i32| -> i32 { i + outer_var.get() };
    println!("closure_annotated: {}", closure_annotated(1));
    outer_var.set(outer_var.get() * 100);
    println!("closure_annotated2: {}", closure_annotated(1));
}

内容的提问来源于stack exchange,提问作者mascai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 13:17:24