2014-11-15 42 views
1

我定義了一個Attribute類型,我有一個Vec<Attribute>,我正在循環檢索「最好」的一個。這是類似於我第一次嘗試:Rust - 如何從for循環中檢索用戶定義的類型

let mut best_attr = &Attribute::new(); 
for a in attrs.iter() { 
    if is_best(a) {  // simplified for example 
     best_attr = a; 
    } 
} 
root.attr = *best_attr; // root is a node in a tree structure 

我有以下編譯錯誤:

    .../src/main.rs:94:21: 94:31 error: cannot move out of dereference of `&`-pointer 
    .../src/main.rs:94   root.attr = *best_attr; 
                 ^~~~~~~~~~ 
    

    一些尋找解決的辦法後,我做了以下解決錯誤

  1. #[deriving(Clone)]屬性添加到我的Attribute結構
  2. 用替換最後一個語句3210

我不完全理解這是爲什麼會起作用,我覺得這是對我遇到的問題的粗略解決方案。這是如何解決錯誤的,這是解決這個問題的正確方法嗎?

+0

不是Rust專家,但是IIRC,它是因爲'root'與'best_attr'有不同的作用域,''root'有時候可以回收'best_attr'的內存。所以這是不允許的。 clone()提供了一個範圍兼容的拷貝,所以它是允許的。 – WeaponsGrade

+2

簡短回答:它歸結爲Rust的所有權模式。一次只能有一件事擁有一塊數據。 –

+0

請注意,首先創建一個默認屬性是浪費的,您可以將'best_attr'設置爲'None',然後在您的循環中使用'best_attr = Some(a)'。當然,最後需要進行一些模式匹配。 –

回答

1

遇到鐵鏽的內存模型的基礎:

  • 每個對象都可以(!而且必須)由僅正好一個其他對象所擁有的
  • 大多數類型從未隱含複製和始終移動(也有一些例外:類型爲Copy

採取此代碼爲例如:

let x = String::new(); 
let y = x; 
println!("{}", x); 

它生成錯誤:

<anon>:4:20: 4:21 error: use of moved value: `x` 
<anon>:4  println!("{}", x); 
          ^

x,String類型的,是不能夠複製隱式,因此一直移動yx不能再使用。


因此,在你的代碼,當你寫

root.attr = *best_attr; 

你第一次提領參考best_attr,則解除引用的值賦給root.attr。但是您的Attribute類型不是Copy,因此此作業應爲移動

然後,編譯器會抱怨:

error: cannot move out of dereference of `&`-pointer 

事實上,best_attr&引用,它讓你把它後面的值(它甚至不允許修改它的所有權)。允許這樣的舉動會使對象將參考背後的價值置於未定義的狀態,這正是魯斯特所要阻止的。


在這種情況下,你最好的選擇確實是創建具有相同的值作爲第一位的,這也正是性狀Clone是爲做了一個新的對象。

內部實現的編譯器允許您只需使用#[deriving(Clone)]標記您的結構爲Clone -able,只要所有的屬性都CopyClone。在更復雜的情況下,你必須親自實施這個特質。