如何解决"creates a temporary variable which is freed while still in use"?
How to resolve "creates a temporary variable which is freed while still in use"?
我正在尝试使用 while
循环为我的自定义 List<T>
实施 Debug
。
use std::cell::RefCell;
use std::rc::Rc;
type Link<T> = Option<Rc<RefCell<Node<T>>>>;
struct Node<T> {
val: T,
next: Link<T>,
}
struct List<T> {
head: Link<T>,
tail: Link<T>,
len: usize,
}
use std::fmt;
impl<T: fmt::Debug> fmt::Debug for List<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut temp = &self.head;
while let Some(r) = temp {
write!(f, "{:?} -> ", r.borrow().val);
temp = &r.borrow().next; // ERROR
}
write!(f, "[]")
}
}
error[E0716]: temporary value dropped while borrowed
--> src/lib.rs:21:21
|
21 | temp = &r.borrow().next; // ERROR
| ^^^^^^^^^^ -
| | |
| | temporary value is freed at the end of this statement
| | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `std::cell::Ref<'_, Node<T>>`
| creates a temporary which is freed while still in use
| a temporary with access to the borrow is created here ...
|
= note: consider using a `let` binding to create a longer lived value
我知道我正在引用临时值 r
,这很糟糕。是否有解决此问题的优雅且惯用的解决方案?
Rustaceans 是否有任何 Rust 代码的借用模式?我知道一种这样的模式是 std::mem::replace
获取一个值的所有权,只有当我们有 &mut T
时才有效,有些人称之为印第安纳琼斯模式
我问了the same question on the Rust User's Forum and got an answer from alice:
impl<T: fmt::Debug> fmt::Debug for List<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut temp = self.head.clone();
while let Some(r) = temp {
write!(f, "{:?} -> ", r.borrow().val);
temp = r.borrow().next.clone();
}
write!(f, "[]")
}
}
The reason for this is that borrow()
returns a guard with a destructor, and you can only access references into the RefCell
while that guard is still active. So without cloning an Rc
, you would need to keep all the guards from each iteration around, but the loop destroys the previous guard when advancing to the next iteration. An Rc
clone lets you access the next node without going through the guard, hence sidestepping the issue.
我正在尝试使用 while
循环为我的自定义 List<T>
实施 Debug
。
use std::cell::RefCell;
use std::rc::Rc;
type Link<T> = Option<Rc<RefCell<Node<T>>>>;
struct Node<T> {
val: T,
next: Link<T>,
}
struct List<T> {
head: Link<T>,
tail: Link<T>,
len: usize,
}
use std::fmt;
impl<T: fmt::Debug> fmt::Debug for List<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut temp = &self.head;
while let Some(r) = temp {
write!(f, "{:?} -> ", r.borrow().val);
temp = &r.borrow().next; // ERROR
}
write!(f, "[]")
}
}
error[E0716]: temporary value dropped while borrowed
--> src/lib.rs:21:21
|
21 | temp = &r.borrow().next; // ERROR
| ^^^^^^^^^^ -
| | |
| | temporary value is freed at the end of this statement
| | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `std::cell::Ref<'_, Node<T>>`
| creates a temporary which is freed while still in use
| a temporary with access to the borrow is created here ...
|
= note: consider using a `let` binding to create a longer lived value
我知道我正在引用临时值 r
,这很糟糕。是否有解决此问题的优雅且惯用的解决方案?
Rustaceans 是否有任何 Rust 代码的借用模式?我知道一种这样的模式是 std::mem::replace
获取一个值的所有权,只有当我们有 &mut T
时才有效,有些人称之为印第安纳琼斯模式
我问了the same question on the Rust User's Forum and got an answer from alice:
impl<T: fmt::Debug> fmt::Debug for List<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut temp = self.head.clone();
while let Some(r) = temp {
write!(f, "{:?} -> ", r.borrow().val);
temp = r.borrow().next.clone();
}
write!(f, "[]")
}
}
The reason for this is that
borrow()
returns a guard with a destructor, and you can only access references into theRefCell
while that guard is still active. So without cloning anRc
, you would need to keep all the guards from each iteration around, but the loop destroys the previous guard when advancing to the next iteration. AnRc
clone lets you access the next node without going through the guard, hence sidestepping the issue.