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

关于Rust Refs与Derefs的理解正确性确认请求

Rust引用与解引用的疑问确认

案例1

fn main() {
    let x = 5;
    let y = x;
    assert_eq!(5, y);        
    println!("y = {}", y);
}

Q1:若使用assert_eq!(5, &y)会报错“no implementation for {integer} == &{integer}”,是否因为y作为原始类型在栈上克隆了x的值5?

A1:完全正确。整数这类原始类型实现了Copy trait,执行let y = x时会直接在栈上复制x的值,y是一个独立的i32类型变量。当你写&y时,得到的是&i32类型的引用,而assert_eq!要求左右两边类型必须能匹配(或实现对应的PartialEq),Rust并没有为{integer}和&{integer}实现直接比较的逻辑,所以会报错。

案例2

fn main() {
    let x = 5;
    let y = &x;
    assert_eq!(5, *y);         
    println!("y = {}", y);
}

Q2:这是否是原始类型场景下强制创建引用而非克隆的方式?此时y是否存储了x的栈地址?

A2:是的。let y = &x明确创建了x的不可变引用,y的类型是&i32,它存储的就是x在栈上的内存地址。通过*y解引用这个地址,就能获取到x的实际值5,所以assert_eq!(5, *y)可以正常执行。

案例3

fn main() {
    let x = String::from("Five");
    let y = &x;
    assert_eq!("Five", y);         
    println!("y = {}", y);
}

Q3:若x是堆分配的String,使用assert_eq!("Five", y)即可生效(无需*y),是否因为编译器的隐式解引用?

A3:没错,这是**Deref强制转换(Deref coercion)**和标准库的PartialEq实现共同作用的结果。String类型实现了Deref<Target = str>,所以&String会被编译器自动隐式转换为&str;而字符串字面量"Five"的类型本身就是&str,两者类型匹配,同时标准库为&str和&String(或者说转换后的&str)实现了PartialEq,因此可以直接用assert_eq!比较。

案例4

fn main() {
    let x = 5;
    let &y = &x;
    let &z = &&x;
    assert_eq!(5, *z); 
    println!("y = {}", z);
}

Q4:该代码中assert_eq!(5, *z)可行,但assert_eq!(5, z)不行,这是否不属于链式引用的自动解析场景?

A4:这和链式引用自动解析无关,本质是模式匹配的结果:

  • let &y = &x:&x是&i32类型,模式&y会匹配这个外层引用,把引用指向的x的值(5)绑定给y,所以y的类型是i32。
  • let &z = &&x:&&x是&&i32类型,模式&z匹配的是最外层的那个引用,把内层的&i32绑定给z,所以z的类型是&i32,而非i32。

因此assert_eq!(5, z)会因为类型不匹配(i32 vs &i32)报错,而*z解引用后得到i32类型的值,就能和5正常比较。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 02:31:08