2014-01-23 27 views
7

我是一個鐵鏽新手,試圖通過玩弄它的語言。我已經打在試圖從一個函數返回一個數組的一些問題:如何從函數返回擁有的數組?

struct Widget { 
    thingies: ~[int] 
} 

impl Widget { 
    fn new() -> Widget { 
     Widget { thingies: ~[4, 8, 15, 16, 23, 42] } 
    } 

    fn somethings(&self) -> ~[int] { 
     self.thingies 
    } 
} 

fn main() { 
    let widget = Widget::new(); 
    let wotsits = widget.somethings(); 
} 

這當然無法編譯與此錯誤:

pointers.rs:11:8: 11:21 error: cannot move out of dereference of & pointer 
pointers.rs:11   self.thingies 

在這種情況下,代碼示例看起來不爽,所有我試圖做的是從實現的結構中拉出一個數組。借來的指針並不重要,這只是我試圖存儲數據的方式。

有關如何正確提取我的數組的任何提示?

順便說一句,我使用的防鏽0.8

+0

'〜'是一個獨特的指針,只能有其中之一(爲相同的值)。它們不能像原始C指針那樣被複制(別名)。試圖創建另一個值(返回值)將該值從原始指針移出,這會使'thingies'和整個'self'不確定,這當然是不允許的。你可能打算返回一個借來的指針,而不是去掉'self.thingies'。 – hamstergene

+0

〜[T]被稱爲*矢量*,而不是*數組*。人們通常在兩者之間進行區分的區別在於,陣列是靜態大小的,而矢量可以增長或縮小。 –

回答

8

你的代碼不能編譯的原因是唯一的e指針~只能擁有一個所有者。編譯器阻止您編寫容易出錯的代碼。您可以決定返回thingies的副本,對thingies的引用或一些thingies(它是對矢量數據或其一部分的引用)。

複印溶液

struct Widget { 
    thingies: ~[int] 
} 

impl Widget { 
    fn new() -> Widget { 
     Widget { thingies: ~[4, 8, 15, 16, 23, 42] } 
    } 

    fn somethings(&self) -> ~[int] { 
     self.thingies.clone() 
    } 
} 

參考溶液

struct Widget { 
    thingies: ~[int] 
} 

impl Widget { 
    fn new() -> Widget { 
     Widget { thingies: ~[4, 8, 15, 16, 23, 42] } 
    } 

    fn somethings<'a>(&'a self) -> &'a~[int] { 
     &self.thingies 
    } 
} 

切片溶液

struct Widget { 
    thingies: ~[int] 
} 

impl Widget { 
    fn new() -> Widget { 
     Widget { thingies: ~[4, 8, 15, 16, 23, 42] } 
    } 

    fn somethings<'a>(&'a self) -> &'a[int] { 
     self.thingies.as_slice() 
    } 
} 

要UND您需要了解參考和切片解決方案,瞭解'a意味着什麼:它表示一個生命週期,而&'a是一種告訴編譯器該引用永遠不會超過它引用的對象的方式,在這種情況下,它是一個Widget。

這些解決方案也有一些限制:您無法修改您當前引用的對象,因爲這樣做會導致引用無效的可能性。

如果你返回一個可變引用,你當然可以修改東西。伴隨一生的一個可變的引用將被寫入&'a mut T

struct Widget { 
    thingies: ~[int] 
} 

impl Widget { 
    fn new() -> Widget { 
     Widget { thingies: ~[4, 8, 15, 16, 23, 42] } 
    } 

    fn somethings<'a>(&'a mut self) -> &'a mut ~[int] { 
     &mut self.thingies 
    } 
} 

注意我相信拉斯特0.8,你需要寫&'self,而不是&'a因爲自定義名稱的壽命並沒有被支持。我也在0.9中寫了這個。

編輯:刪除冗餘生命週期聲明。

+0

除非需要在結構中借用指針,否則不需要在結構上放置生命週期註釋。不是這種情況。你可以參數化'somethings'方法:'某些事情<'a><(&'a mut self) - >&'a mut〜[int] ...'。 –

+0

@Vladimir Matveev謝謝,我更新了這篇文章。 –

+0

關於0.8評論,我發現代碼與&'a一樣工作。我不需要把它改成'自我'。 –

4

=== 編輯 ===

魯斯特1穩定

~[T]成爲Vec<T>,但(語法除外)相同的問題適用,作爲Vec仍然擁有獨特的所有者。簡而言之,somethings僅提及自我,並且(通過參考)它不能成爲thingies的所有者。遊樂場鏈接Rust 1版本:https://play.rust-lang.org/?gist=50ec1acdc684e53fd5f9&version=stable

鏽病的所有權模式是非常核心的語言,所以更多的信息,我會建議在ownershipborrowing

=== 編輯完 ===看着偉大的官方文檔

在Rust中,.self之後,自動解除引用self,所以這是錯誤提到的dereference of & pointer

現在一樣的東西的所有權是你cannot move out of提領部分:

let widget = Widget::new(); // widget owns the unique pointer to self 
    let wotsits = widget.somethings(); // if this worked, ownership of 
             // unique pointer to thingies would be 
             // moved to wotsits 

你可以借到一樣的東西的參考,而不是:

fn somethings<'a>(&'a self) -> &'a~[int] { 
    &self.thingies 
} 

或明確地返回一樣的東西的副本

fn somethings(&self) -> ~[int] { 
    self.thingies.clone() 
} 
+0

討厭再次嘗試,但更多人試圖更新1.0之前的問題。讓我們有一個[更大的羣聊](http://chat.stackoverflow.com/rooms/62927/rust)。 – Shepmaster

2

您不能移出借用指針,正如其他答案中所述。但是你可以通過值或所擁有的指針傳遞self,那麼你將能夠返回擁有矢量:

struct Widget { 
    thingies: ~[int] 
} 

impl Widget { 
    fn somethings(self) -> ~[int] { 
     self.thingies 
    } 
}