关于Rust中多次使用引用操作符`&`不会触发编译错误的技术疑问
为什么在Rust中对变量多次使用引用操作符
&不会触发编译错误? 嘿,我来帮你理清这个有点反直觉的问题——你是不是看到代码里的File::open(&&&path)时一脸疑惑?明明path已经是&str类型了,连续套三层&居然还能正常编译,这可不太像Rust一贯的“严格”风格对吧?
先把完整的可运行代码贴出来方便分析:
use std::{fs::File, io::Read}; use std::any::type_name_of_val; fn main() { let path: &str = "foo.txt"; let mut file: File = match File::open(&&&path) { Ok(f) => f, Err(reason) => panic!("Could not open file: {path}, reason: {reason}"), }; let mut data: String = String::new(); if let Err(e) = file.read_to_string(&mut data) { panic!("Failed to read file: {}", e); } println!("Read content: {}", data); }
核心原因在于Rust的自动解引用(Deref Coercion)和AsRef trait的配合:
- 首先,
File::open方法的参数要求是实现了AsRef<Path>的类型,而&str正好实现了这个trait,所以直接传path(&str)是完全没问题的。 - 那为什么传
&&&path(也就是&&&str)也可以?因为Rust会自动对多层引用进行解引用转换。对于任何实现了Dereftrait的类型(&T本身就实现了Deref<Target = T>),编译器会自动把&&&str一层一层解引用,最终得到&str,而&str满足AsRef<Path>的要求,所以编译器不仅不会报错,还会默默帮你完成这个转换。
你可以加一行代码验证一下类型:
println!("Type of &&&path: {}", type_name_of_val(&&&path));
运行后会输出&&&str,但传给File::open时,编译器自动将其转换为了符合要求的&str。
不过这里也要提一句:虽然编译器允许这种写法,但从代码可读性来说,没必要故意加多层引用,保持代码简洁清晰才是更好的选择——毕竟不是所有人都能第一时间反应过来这是自动解引用在起作用~
备注:内容来源于stack exchange,提问作者auraham
相关产品推荐
相关产品推荐

