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

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中编译它吗?

===============>>#1 票数:13 已采纳

甚至可以在安全的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俩。 VecHashSet这样的集合保证它们不会在析构函数中访问其通用参数。 他们使用不稳定的#[may_dangle]功能将此信息传达给编译器。

也可以看看:

  ask by moatPylon translate from so

未解决问题?本站智能推荐: