2017-06-09 14 views
0

這裏例如讀/寫:HashMap的:借在同一時間的什麼,我想實現

use std::collections::HashMap; 

fn f(a: &i32, b: &mut i32) { 
} 

fn main() { 

    let mut map = HashMap::new(); 

    map.insert("1", 1); 
    map.insert("2", 2); 

    { 
     let a: &i32 = map.get("1").unwrap(); 
     println!("a: {}", a); 

     let b: &mut i32 = map.get_mut("2").unwrap(); 
     println!("b: {}", b); 
     *b = 5; 
    } 
    println!("Results: {:?}", map) 
} 

所以我有f接受兩個引用mut而不是mut。 並且在HashMap內部具有值f。顯然這是行不通的,因爲HashMap::getHashMap::get_mut借用可變而且不能同時變化。

注意:在真正的代碼,我使用複雜的大結構,而不是i32,所以不好克隆。

但事實上,我借可變/不可變的兩個不同的東西,像 :

struct HashMap { 
    a: i32, 
    b, i32, 
} 
let mut map = HashMap { a: 1, b: 2 }; 
let a = &map.a; 
let b = &mut map.b; 

任何方式指向編譯器,其實這是安全的代碼?

我怎麼看它有可能在這個具體的例子 解決與iter_mut

{ 
    let mut a: &i32 = unsafe { mem::uninitialized() }; 
    let mut b: &mut i32 = unsafe { mem::uninitialized() }; 
    for (k, mut v) in &mut map { 
     match *k { 
      "1" => {a = v; } 
      "2" => { b = v; } 
      _ => {} 
     } 
    } 
    f(a, b); 
} 

但它與HashMap::get/get_mut

回答

1

TL比較慢的; DR:你需要改變的類型HashMap


全光照時g一種方法,編譯器檢查方法的內部或執行任何運行時模擬:它僅基於方法簽名的所有權/借用檢查分析。

在你的情況,這意味着:使用get_mut會性情不定地借用了整個HashMap只要參考

  • 使用get將借用整個HashMap只要參考生活,
  • 住。

並且因此,是不可能用HashMap<K, V>在同一時間同時獲得一個&V&mut V


的變通,因此,爲避免對&mut V完全的需要。

這可以通過使用CellRefCell來完成:

  • 把你HashMapHashMap<K, RefCell<V>>
  • 使用get在這兩種情況下,
  • 使用borrow()得到參考和borrow_mut()得到一個可變參考。

這將在每次調用borrow()borrow_mut()時間增加一個運行時檢查,如果你曾經嘗試錯誤地使用它們(如果這兩個鍵是相等的,不像你的期望),就會死機。


至於使用字段:這是有效的,因爲編譯器可以推斷每個字段的借用狀態。

+0

但是'iter_mut'工作,沒有運行時檢查,如果我可以通過'IterMut'跳轉到特定的鍵,那麼可以使用'HashMap'而無需通過'RefCell'進行運行時檢查。 – user1244932

+1

@ user1244932:'IterMut'保證它只產生一次單個引用,按照它的語義:你永遠不能通過'IterMut'返回已經產生的元素,這樣得到的元素藉用原始映射(因此也不能產生另一個元素)。 –