Rust报错`temporary value dropped while borrowed`:list与lista的差异疑问
Rust临时值生命周期差异问题解析
问题背景
我编写了如下Rust代码:
enum List<'a> { Cons(i32, Box<&'a List<'a>>), Nil, }; let list= Cons(10, Box::new(&Nil)); let lista = Cons(5, Box::new(&Cons(10, Box::new(&Nil)))); match lista { Cons(x,_) => println!("{}",x), Nil => () }
运行后编译器报错:
21 | let lista = Cons(5, Box::new(&Cons(10, Box::new(&Nil)))); | ^^^^^^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement | | | creates a temporary which is freed while still in use
我理解Cons(10, Box::new(&Nil))会被释放导致报错,但当我将match的对象改为list时:
match list { Cons(x,_) => println!("{}",x), Nil => () }
代码却能正常运行,我认为Nil同样是临时值会在语句结束时被释放,请问list和lista之间的差异是什么?
核心差异解析
1. Nil是静态生命周期的全局实例
Nil是枚举的无数据变体,它不包含任何动态分配的数据或引用。在Rust中,这类无数据的枚举变体默认拥有'static生命周期——它会永久存在于程序运行期间,不会被当作临时栈值释放。
当你写&Nil时,引用指向的是一个全局静态的Nil实例,而非临时创建的栈上值。因此list里的Box::new(&Nil)保存的是指向静态Nil的引用,不存在生命周期不匹配的问题。
2. Cons(10, Box::new(&Nil))是临时栈值
lista中的Cons(10, Box::new(&Nil))是一个临时创建的Cons实例,它被分配在栈上,仅在当前语句的范围内有效。当你取它的引用&Cons(...)并放入Box时,这个引用的生命周期只到当前语句结束。但lista本身会存活到后续的match语句,这就导致引用指向的临时值已经被释放,而lista还在持有这个引用——直接触发Rust的生命周期检查错误。
3. 生命周期推导的本质区别
- 对于
list:Box<&'a List<'a>>中的引用指向'static的Nil,编译器会自动将'a推导为'static,和list的生命周期完全兼容。 - 对于
lista:内部临时Cons值的生命周期远短于lista的生命周期,不存在一个能同时覆盖两者的有效生命周期'a,因此编译器拒绝通过。
内容的提问来源于stack exchange,提问作者MichealRay
相关产品推荐
相关产品推荐

