2017-07-08 66 views
6

對於有關代碼組織的原因,我需要編譯器接受以下(簡化)代碼:如何在向量之後創建借用值時向矢量添加引用?

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中編譯它?

回答

8

甚至有可能在安全的Rust中編譯這個嗎?

不,你想要做的是本質上不安全

Vec包含一個變量的引用,該變量在Vec本身被刪除之前將被刪除。這意味着Vec的析構函數可以訪問不再有效的引用。析構函數可以選擇取消引用其中一個值,從而破壞Rust的內存安全保證。

Vec很可能不是這樣,但編譯器不知道什麼關於Vec什麼特殊的可能與自定義類型相比。

注:在一個範圍值,以相反的順序被丟棄在創建

當編譯器會告訴你,你需要重新安排你的代碼。 你實際上並沒有說什麼侷限性爲「有關代碼組織的理由」,但直接的解決方法是:

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); 
} 

有一天,當非詞彙生存期被添加到Rust時,可能能夠使用drop來影響借用。

參見:

+0

基本上,計算值,並推動他們都依賴於相同的值相同的情況,但不同的價值觀有不同的條件,使您的第一種情況意味着複製'if'語句。這些值不能移動到矢量中,因爲矢量必須包含對特徵對象的引用。但是你最後的情況正是我所追求的。 – moatPylon