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

Rust中高间接层引用可赋值给低间接层,反之不行的原因

Rust引用层级转换的规则与本质差异

一、高间接层级引用可赋值给低层级的情况

Rust允许将更高间接层级的引用赋值给更低间接层级的引用,比如把&&&&&&i32类型赋值给&i32类型,编译器会自动处理:

fn main() {
    let mut some_number = 5;

    // 将 &&&&&&i32 赋值给 &i32,编译通过
    let reference : &i32 = &&&&&&some_number;
}

这种行为在函数参数传递中同样生效:

fn main() {
    let num = 5;

    // ref1 是 &&i32 类型
    let ref1 = &#
    
    // 把 &&i32 传递给接受 &i32 的参数,编译通过
    func(ref1);
}

fn func(test: &i32) {
    println!("^^^^ This works!");
}

这背后是**自动解引用(automatic dereferencing)**机制:编译器会按需对源类型进行多次解引用,直到其类型与目标类型匹配——每一次解引用&T都会得到T,如果T还是引用,就继续解引用,直到得到非引用类型或者匹配目标类型为止。

二、低间接层级引用无法赋值给高层级的情况

反过来,Rust禁止将低间接层级的引用赋值给更高层级的引用,比如试图把&i32赋值给&&i32会直接报错:

fn main() {
    let num = 5;
    
    // 尝试将 &i32 赋值给 &&i32,编译错误
    let ref1 : &&i32 = #
}

这段代码会触发expected &i32, found integer的编译错误。函数参数传递时也会出现类似问题:

fn main() {
    let num = 5;
    
    // ref1 是 &&&i32 类型
    let ref1 = &&#
    
    // 尝试将 &&&i32 传递给接受 &&&&&i32 的参数,编译错误
    func(ref1);
}

fn func(test: &&&&&i32) {
    println!("^^^^^^^^ This does not work!")
}

这里的报错信息不是预期的expected &&&&&i32, found &&&i32,而是expected &&i32, found integer——这是因为编译器在类型匹配时,会同时尝试对源和目标类型进行解引用,直到其中一方不再是引用类型,以此寻找可能的匹配路径,但最终还是无法找到合法的转换方式,所以报错。

三、核心差异的本质原因

高转低可行、低转高被禁止的核心原因在于引用的语义与内存安全:

  • 高转低的合理性:更高层级的引用本质上是对低层级引用的引用,多次解引用后最终指向的是同一个底层值。自动解引用只是让编译器帮我们省去手动写***...&x的麻烦,这个过程是安全的——因为每一步解引用都是访问已经存在的引用指向的对象,不会产生悬空引用或者非法内存访问。
  • 低转高的不可行性:如果要把&i32转换成&&i32,意味着需要创建一个新的引用,指向原来的&i32引用。但原来的&i32可能是一个临时值(比如&num是一个临时引用),如果编译器自动创建更高层级的引用,这个新引用可能会指向一个已经被销毁的临时引用,导致悬空引用,违反Rust的内存安全规则。因此Rust不允许这种自动转换,必须由开发者显式创建合法的高层级引用。

比如要实现低转高的合法转换,需要显式操作:

fn main() {
    let num = 5;
    let ref1 = # // &i32
    let ref2 = &ref1; // &&i32,合法
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 22:25:30