
[英]Can I make a struct that works with both values and borrowed references to a trait?
[英]How do I add references to a container when the borrowed values are created after the container?
出于与代码组织有关的原因,我需要编译器接受以下(简化的)代码:
fn f() {
let mut vec = Vec::new();
let a = 0;
vec.push(&a);
let b = 0;
vec.push(&b);
// Use `vec`
}
编译器抱怨
error: `a` does not live long enough
--> src/main.rs:8:1
|
4 | vec.push(&a);
| - borrow occurs here
...
8 | }
| ^ `a` dropped here while still borrowed
|
= note: values in a scope are dropped in the opposite order they are created
error: `b` does not live long enough
--> src/main.rs:8:1
|
6 | vec.push(&b);
| - borrow occurs here
7 | // Use `vec`
8 | }
| ^ `b` dropped here while still borrowed
|
= note: values in a scope are dropped in the opposite order they are created
但是,我很难说服编译器将向量放在它引用的变量之前。 vec.clear()
不起作用, drop(vec)
也不起作用。 mem::transmute()
也不起作用(强制vec
为'static
)。
我发现的唯一解决方案是将引用转换为&'static _
。 还有其他办法吗? 甚至可以在安全的Rust中编译它吗?
甚至可以在安全的Rust中编译它吗?
否。通常情况下,您要尝试做的事情本质上是不安全的。
集合包含对变量的引用,该变量将在删除集合本身之前被删除。 这意味着该集合的析构函数可以访问不再有效的引用。 析构函数可以选择取消引用其中一个值,从而破坏Rust的内存安全性保证。
注意:作用域中的值以与创建时相反的顺序删除
正如编译器告诉您的那样,您需要重新排序代码。 您实际上并未说 “与代码组织有关的原因” 的局限性是什么 ,但直接的解决方法是:
fn f() {
let a = 0;
let b = 0;
let mut vec = Vec::new();
vec.push(&a);
vec.push(&b);
}
一个不太明显的是:
fn f() {
let a;
let b;
let mut vec = Vec::new();
a = 0;
vec.push(&a);
b = 0;
vec.push(&b);
}
综上所述,一旦启用了非词性生存期 ,您的原始代码就可以使用! 借用检查器对值需要保留多长时间有了更细致的了解。
但是等一下 ; 我只是说过,如果集合中的某个值在集合之前被删除,则该集合可能会访问无效的内存,现在编译器允许这种情况发生吗? 是什么赋予了?
这是因为标准库给我们带来了一个sneak俩。 像Vec
或HashSet
这样的集合保证它们不会在析构函数中访问其通用参数。 他们使用不稳定的#[may_dangle]
功能将此信息传达给编译器。
也可以看看:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.