Rust 当在容器之后创建借用的值时,如何向容器添加引用?

Rust 当在容器之后创建借用的值时,如何向容器添加引用?,rust,borrow-checker,Rust,Borrow Checker,出于与代码组织相关的原因,我需要编译器接受以下(简化)代码: 编译器抱怨 错误:`a`寿命不够长 -->src/main.rs:8:1 | 4 |向量推送(&a); |-借用发生在这里 ... 8 | } |^`a`在还借来的时候掉在这里了 | =注意:范围中的值按与创建顺序相反的顺序删除 错误:`b`活得不够长 -->src/main.rs:8:1 | 6 |向量推送(&b); |-借用发生在这里 7 |//使用“vec”` 8 | } |^`b`在还借来的时候就掉在这里了 | =注意:范围中

出于与代码组织相关的原因,我需要编译器接受以下(简化)代码:

编译器抱怨

错误:`a`寿命不够长
-->src/main.rs:8:1
|
4 |向量推送(&a);
|-借用发生在这里
...
8 | }
|^`a`在还借来的时候掉在这里了
|
=注意:范围中的值按与创建顺序相反的顺序删除
错误:`b`活得不够长
-->src/main.rs:8:1
|
6 |向量推送(&b);
|-借用发生在这里
7 |//使用“vec”`
8 | }
|^`b`在还借来的时候就掉在这里了
|
=注意:范围中的值按与创建顺序相反的顺序删除
然而,我很难说服编译器在引用变量之前删除向量
vec.clear()
不起作用,
drop(vec)
mem::transmute()
也不起作用(强制
vec
成为
静态的

我找到的唯一解决方案是将引用转换为
&'static
。还有别的办法吗?甚至可以在安全的环境中编译这个吗

甚至可以在安全的环境中编译这个吗

不。在一般情况下,您试图做的是本质上不安全的

集合包含对变量的引用,该变量将在集合本身被删除之前被删除。这意味着集合的析构函数可以访问不再有效的引用。析构函数可以选择取消引用其中一个值,从而破坏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);
}

总之,一旦启用,您的原始代码将正常工作!“借用检查器”对于值的生存时间变得更加精细

但是等待;我刚才说过,如果集合中的值在集合之前被删除,那么集合可能会访问无效内存,现在编译器允许这种情况发生?有什么好处

这是因为标准图书馆对我们耍了一个诡计。像
Vec
HashSet
这样的集合保证它们不会访问析构函数中的泛型参数。他们使用该特性将此信息传递给编译器

另见:


基本上,计算值和推送值取决于相同值的相同条件,但不同的值具有不同的条件,因此第一种情况意味着复制
if
语句。无法将值移动到向量中,因为向量必须包含对特征对象的引用。但你的最后一个案子正是我要找的。我一直在想,
let a语法。@BHustus请参见。
fn f() {
    let a;
    let b;

    let mut vec = Vec::new();
    a = 0;
    vec.push(&a);
    b = 0;
    vec.push(&b);
}