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
相关产品推荐
相关产品推荐

