实现Deref trait返回&String报错,为何PathBuf可返回引用?
关于Deref trait实现返回引用的问题解析
你的代码为什么报错
你写的MyDir的Deref实现里,deref函数内的txt是个局部变量——它是在函数栈上创建的临时字符串,函数执行完毕后就会被销毁。返回它的引用相当于返回了一个指向已释放内存的指针,也就是悬垂引用,Rust的安全机制自然会直接报错拦截。
PathBuf的Deref实现为啥没问题
看PathBuf的代码:
[stable(feature = "rust1", since = "1.0.0")] impl ops::Deref for PathBuf { type Target = Path; #[inline] fn deref(&self) -> &Path { Path::new(&self.inner) } }
这里的Path::new根本没创建新的所有权数据。Path本身是个引用类型(胖指针),&self.inner是指向PathBuf自身持有的inner字段的引用,Path::new只是把这个引用转换成&Path类型而已。返回的&Path实际引用的是PathBuf结构体自身拥有的数据,生命周期和self完全一致,完全符合Rust的安全规则。
修正你的代码的几种方式
如果你非要通过Deref返回格式化后的字符串引用,必须把这个格式化后的字符串存在MyDir里,不能临时创建:
use std::ops; struct MyDir { path: String, display_str: String, // 预先存好格式化后的字符串 } impl MyDir { fn new(path: String) -> Self { let display_str = format!("Dir[path = {}]", path); MyDir { path, display_str } } } impl ops::Deref for MyDir { type Target = String; fn deref(&self) -> &String { &self.display_str } } fn main() { let dir = MyDir::new("/home/user".to_string()); println!("{}", *dir); // 输出 Dir[path = /home/user] }
要是只是需要格式化后的字符串,其实没必要实现Deref,给MyDir加个方法更直接:
use std::ops; struct MyDir { path: String, } impl MyDir { fn display(&self) -> String { format!("Dir[path = {}]", self.path) } } fn main() { let dir = MyDir { path: "/home/user".to_string() }; println!("{}", dir.display()); }
内容的提问来源于stack exchange,提问作者Saber
相关产品推荐
相关产品推荐

