![](/img/trans.png)
[英]Simplify Rust extension trait lifetimes when using Add trait
[英]What are the rules for lifetimes in Rust when using boxed trait objects?
下面的代码无法编译并出现错误 E0597:借用的值(二)寿命不够长。
fn main() {
let one = String::from("one");
let mut _it: Box<dyn Iterator<Item=char>> = Box::new(one.chars());
let two = String::from("two");
_it = Box::new(two.chars());
}
但是,如果我使用对特征 object 的引用而不是盒装特征 object 它会起作用:
fn main() {
let one = String::from("one");
let mut _it: &dyn Iterator<Item=char> = &one.chars();
let two = String::from("two");
_it = &two.chars();
}
另外,如果我不使用特征 object,它也可以工作:
fn main() {
let one = String::from("one");
let mut _it: Box<_> = Box::new(one.chars());
let two = String::from("two");
_it = Box::new(two.chars());
}
为什么?
让我们一一列举。
在您的第一个示例中,问题很微妙,并由错误消息提示
8 | _it = Box::new(two.chars());
| ^^^^^^^^^^^ borrowed value does not live long enough
9 | }
| -
| |
| `two` dropped here while still borrowed
| borrow might be used here, when `_it` is dropped and runs the destructor for type `Box<dyn Iterator<Item = char>>`
|
= note: values in a scope are dropped in the opposite order they are defined
正如注释所说,值的删除顺序与它们定义的顺序相反。 由于two
在第 6 行定义, _it
在第 4 行定义(未赋值),编译器会在尝试销毁_it
末尾的 _it 之前先销毁two
。但是当我们到达 function 末尾时, _it
持有对two
的引用(第 8 行),强加的排序会破坏two
而_it
仍然持有对它的引用。 _it
的析构函数可以观察到被破坏的值two
,所以这是不允许的。
为什么还有析构函数? 因为特征 object dyn Iterator...
- 就像任何其他特征 object -可以包含一些具有析构函数的动态类型。 那个析构函数可能会观察到它可能引用的东西; 据编译器所知,这是two
. 虽然实际的Chars
类型不会遇到这个问题,但我可以想出这样一种类型并将其粘贴到dyn Iterator...
中。 因此对于 trait 对象,删除值的顺序总是很重要。
解决办法是改变定义的顺序:
fn main() {
let one = String::from("one");
let two; // Notice the definition, before `_it` so it gets dropped *after*
let mut _it: Box<dyn Iterator<Item=char>> = Box::new(one.chars());
two = String::from("two");
_it = Box::new(two.chars());
}
在第二个示例中,您使用的是普通引用。 由于普通引用没有析构函数,因此没有析构函数可以在运行时潜在地观察到被销毁的值,并且销毁值的顺序并不重要; 所以它编译得很好。
在第三个示例中,不涉及特征对象,就编译器而言,装箱类型只是普通类型(就像Box<u32>
)。 因为它是一个具体类型,所以编译器可以找出Box
中的类型(它是一个Chars
,并持有某个生命周期的引用),有一个普通的析构函数(什么都不做),因此Box
有一个普通的析构函数简单解除分配的析构函数; 所以two
实际上在_it
之前被销毁并不重要,因为_it
肯定无法在其析构函数中观察到two
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.