G
N
I
D
A
O
L

“&u64”,“&mut u64”,“&String”,“&mut String” 区别

rust内存中的引用

概念:
&指针本身大小就是4/8个字节(32/64计算机的最大寻址空间)
size_of::<&type>(),无论type是什么,打印的只是指针本身大小(最大寻址空间)

详细说明

| 🏁 对比&u64&mut u64&String

&u64 - 不可变引用

let x: u64 = 42;
let r: &u64 = &x;
 
// 内存布局
Stack:
┌──────────────┐
│  x: u64      │
│  [42]        │  8 字节(实际数据)
├──────────────┤
│  r: &u64     │
│  [0x7fff...] │  8 字节(指针,指向 x)
└──────────────┘
 
// 特性
✅ 可以读取
❌ 不能修改
✅ 可以有多个不可变引用(即`r`能多次赋值变量)

示例

let x = 42u64;
let r1 = &x;
let r2 = &x;  // ✅ 多个不可变引用同时存在
println!("{}", *r1);  // ✅ 可以解引用读取
// *r1 = 100;  // ❌ 编译错误:不能通过不可变引用修改

&mut u64 - 可变引用

let mut x: u64 = 42;
let r: &mut u64 = &mut x;
 
// 内存布局
Stack:
┌──────────────┐
│  x: u64      │
│  [42]        │  8 字节(实际数据,可变)
├──────────────┤
│  r: &mut u64 │
│  [0x7fff...] │  8 字节(指针,指向 x)
└──────────────┘
 
// 特性
✅ 可以读取
✅ 可以修改
❌ 同时只能有一个可变引用

示例

let mut x = 42u64;
let r = &mut x;
*r = 100;       // ✅ 可以修改
println!("{}", *r);  // ✅ 可以读取
 
// let r2 = &mut x;  // ❌ 编译错误:不能同时有两个可变引用
// let r3 = &x;      // ❌ 编译错误:有可变引用时不能有不可变引用

指向 String 的不可变引用

let s: String = "hello".to_string();
let r: &String = &s;
 
// 内存布局
Stack:                     Heap:
┌──────────────┐          ┌──────────┐
│  s: String   │          │ "hello"  │
│  ptr: ●──────┼─────────>│ (5 bytes)│
│  cap: 5      │          └──────────┘
│  len: 5      │  24 bytes
├──────────────┤
│  r: &String  │
│  [0x7fff...] │──┐  8 bytes (指向 s)
└──────────────┘  │
                  ↓
            指向上面的 String 结构

示例

let s = String::from("hello");
let r: &String = &s;
println!("{}", r);      // ✅ 可以读取
println!("{}", r.len());  // ✅ 可以调用方法
// r.push_str("!");      // ❌ 不能修改
// s.push_str("!");      // ❌ s 被借用期间也不能修改

三者对比表

类型 大小 可读 可写 多个同时存在 指向的数据大小
&u64 8 字节 8 字节
&mut u64 8 字节 8 字节
&String 8 字节 24 字节(栈)+ 堆数据
&mut String 8 字节 24 字节(栈)+ 堆数据
&Ticket 8 字节 72 字节(栈)+ 堆数据

❗备注:Ticket(自定义类型。有三个String属性)

关键区别

区别 1:可变性(Mutability)

// 不可变引用
let x = 42;
let r = &x;
// *r = 100;  // ❌ 错误
 
// 可变引用
let mut x = 42;
let r = &mut x;
*r = 100;     // ✅ 正确

区别 2:借用规则

let mut x = 42;
 
// 规则1:多个不可变引用可以共存
let r1 = &x;
let r2 = &x;
let r3 = &x;  // ✅ 
 
// 规则2:可变引用独占
let r1 = &mut x;
// let r2 = &mut x;  // ❌ 不能有第二个
// let r3 = &x;      // ❌ 不能混合
 
// 规则3:引用作用域结束后可以重新借用
{
    let r1 = &x;
    println!("{}", r1);
}  // r1 作用域结束
let r2 = &mut x;  // ✅ 

区别 3:指向的数据类型

// 指向简单类型
let n: u64 = 42;
let r: &u64 = &n;  // 指向 8 字节的整数
 
// 指向复杂类型
let s: String = "hello".to_string();
let r: &String = &s;  // 指向 24 字节的 String 结构(不包括堆数据)
 
let ticket: Ticket = Ticket::new(...);
let r: &Ticket = &ticket;  // 指向 72 字节的 Ticket 结构
posted @ 2026-03-05 18:15  Bingo39  阅读(4)  评论(0)    收藏  举报