首页 游戏天地文章正文

Rust 可变引用:变量界的 "独家修改权" &mut

游戏天地 2025年08月08日 21:49 1 admin


Rust 可变引用:变量界的 "独家修改权" &mut


Rust 可变引用:变量界的 "独家修改权"

为啥需要可变引用?

想象一下:你有一份电子合同(变量),现在需要修改其中的条款。如果同时有两个人拿着编辑权限(可变引用),很可能改出两个不同版本,最后乱成一团。Rust 的&mut T(可变引用)就是为了解决这个问题 —— 它像一把专属钥匙,一次只给一个人,确保修改不会冲突。



之前讲的不可变引用适合 "共享阅读",但现实中我们总得修改东西吧?可变引用就是 Rust 给的 "安全修改方案",只不过附带了些 "奇葩但有用" 的规矩。

可变引用基本操作:&mut T怎么玩?

现实类比:编辑微信文档。当你点击 "编辑" 按钮(创建可变引用),别人就只能看不能改;只有你放弃编辑(引用失效),别人才能拿到编辑权。



案例 1:简单的可变引用



  1. 新建项目(如果之前的还在就继续用):
  2. bash
  3. cargo new rust_mutable_demo cd rust_mutable_demo

  4. 编辑src/main.rs:
  5. rust
  6. fn main() { // 注意:变量本身必须是mut的才能创建可变引用 let mut document = String::from("原始合同:甲方欠乙方1元"); // 创建可变引用(获取编辑权) let editor = &mut document; // 现在可以修改了! editor.push_str(",利息0元"); // 打印修改后的结果 println!("修改后:{}", document); }

  7. 编译运行:
  8. bash
  9. cargo run

  10. 输出:
  11. plaintext
  12. 修改后:原始合同:甲方欠乙方1元,利息0元

  13. 关键点:要创建可变引用,变量本身必须用mut声明 —— 就像只有标了 "可修改" 的文档才能被编辑。

可变引用的铁律:"一山不容二虎"

Rust 编译器像个严格的保安,执行着著名的 "一个可变或多个不可变" 规则:



  1. 同一时间,只能有一个可变引用
    防止多人同时修改导致冲突
  2. 有可变引用时,不能有任何不可变引用
    别人正在修改,你看到的版本可能随时变化,干脆不让看
  3. 引用必须始终有效(不超过所有者生命周期)
    这是所有引用的通用规则



案例 2:违反 "一虎 rule" 的后果



修改src/main.rs:



rust

fn main() {    let mut s = String::from("测试");        // 尝试创建两个可变引用——搞事情!    let r1 = &mut s;    let r2 = &mut s; // 编译错误!        println!("{} {}", r1, r2);}



编译报错:



plaintext

cannot borrow `s` as mutable more than once at a time



翻译成人话:"这变量已经被人拿去改了,你等会儿再申请!"



案例 3:可变引用和不可变引用不能共存



rust

fn main() {    let mut s = String::from("测试");        let r1 = &s; // 不可变引用    let r2 = &s; // 再来一个不可变引用,没问题    let r3 = &mut s; // 尝试创建可变引用——报错!        println!("{} {} {}", r1, r2, r3);}



编译报错:



plaintext

cannot borrow `s` as mutable because it is also borrowed as immutable



就像:"有人正在看这份文档呢,你不能同时去修改它!"

如何规避冲突?缩小引用作用域!

现实类比:厕所隔间。虽然一次只能一个人用(一个可变引用),但只要前一个人出来(引用离开作用域),下一个人就能进去了。



案例 4:通过作用域避免冲突



rust

fn main() {    let mut s = String::from("Hello");        // 第一个可变引用的作用域    {        let r1 = &mut s;        r1.push_str(" World");    } // r1在这里失效了        // 现在可以创建新的可变引用了    let r2 = &mut s;    r2.push_str("!");        println!("{}", s); // 输出:Hello World!}



运行正常!因为第一个可变引用在{}内就 "消失" 了,给第二个可变引用腾出了空间。

函数中的可变引用

现实类比:外卖备注修改。你(所有者)把订单号(可变引用)给客服(函数),让他帮忙改备注,改完后权限回到你手里。



案例 5:向函数传递可变引用



rust

// 给字符串增加感叹号(需要修改权限)fn add_exclamation(s: &mut String) {    s.push('!');}fn main() {    let mut message = String::from("Rust真有趣");        // 传递可变引用    add_exclamation(&mut message);    add_exclamation(&mut message); // 可以多次传递,只要不同时存在        println!("{}", message); // 输出:Rust真有趣!!}



运行结果完美!函数通过可变引用临时获得修改权,用完就还,不影响原所有者。

综合案例:游戏角色血量修改

rust

// 显示当前血量(只读)fn show_health(health: &i32) {    println!("当前血量:{}", health);}// 减少血量(需要修改权限)fn take_damage(health: &mut i32, damage: i32) {    *health -= damage; // *是解引用,访问引用指向的值    if *health < 0 {        *health = 0;    }}// 增加血量(需要修改权限)fn heal(health: &mut i32, amount: i32) {    *health += amount;    if *health > 100 {        *health = 100; // 血量上限100    }}fn main() {    let mut player_health = 100;        // 先看看初始血量(不可变引用)    show_health(&player_health);        // 被攻击(可变引用)    take_damage(&mut player_health, 30);    show_health(&player_health); // 现在70        // 治疗(可变引用)    heal(&mut player_health, 20);    show_health(&player_health); // 现在90        // 再被暴击(可变引用)    take_damage(&mut player_health, 100);    show_health(&player_health); // 现在0(濒死)}



运行结果:



plaintext

当前血量:100当前血量:70当前血量:90当前血量:0



这个案例完美展示了规则:每次修改(掉血 / 治疗)时用可变引用,查看时用不可变引用,它们交替出现,从不重叠,所以编译顺利通过。

总结:可变引用是 "可控的修改权"

Rust 的可变引用&mut T看似麻烦,实则是为了保证安全。它像现实中的 "排他性操作许可"—— 确保重要数据在修改时不会被打扰,也不会出现多人修改导致的混乱。记住这个口诀:"要么一个改,要么多个看,千万别捣乱",你就掌握了 Rust 可变引用的精髓!

标题备选

  1. 《Rust 可变引用:变量界的 "独家装修许可证"》
  2. 《为什么 Rust 不让两个变量同时 "搞破坏"?—— 可变引用详解》

简介

本文用编辑文档、外卖备注等生活化类比,详解 Rust 中可变引用(&mut T)的概念、用法及 "一个可变或多个不可变" 的核心限制,通过多个可实操的代码案例,帮助读者理解如何安全地修改共享数据。

关键词

#Rust 可变引用 #独占修改 #借用规则 #&mut T #内存安全

发表评论

泰日号Copyright Your WebSite.Some Rights Reserved. 网站地图 备案号:川ICP备66666666号 Z-BlogPHP强力驱动