2013-07-08 4 views
8

Dla odniesienia używam Rust 0.7.Jak przenieść posiadany wskaźnik

Próbuję utworzyć implementację stosu za pomocą posiadanej listy połączonej i mam problemy.

trait Stack<T> { 
    fn push(&mut self, item : T); 
    fn pop(&mut self) -> Option<T>; 
} 

enum Chain<T> { 
    Link(T, ~Chain<T>), 
    Break 
} 

impl<T> Stack<T> for ~Chain<T> { 
    fn push(&mut self, item : T) { 
     *self = ~Link(item, *self); 
    } 
    fn pop(&mut self) -> Option<T> { 
     None 
    } 
} 

Kiedy próbuję rustc stack.rs pojawia się następujący błąd:

stack.rs:13:28: 13:34 error: cannot move out of dereference of & pointer 
stack.rs:13   *self = ~Link(item, *self); 
             ^~~~~~ 

nie wiem jak mogłem przezwyciężyć lub co mogłem zrobić inaczej na to pozwolić. Wygląda na to, że powinienem móc stworzyć tę strukturę danych bez korzystania z zarządzanych wskaźników, ale nie widziałem zbyt wiele dokumentacji na ten temat. .

+1

należy wdrożyć cechę na '' Łańcucha jak zaakceptowanej odpowiedzi, ale można zachować swój pomysł za pomocą coś jak 'niech ogon = std :: util :: zastąpić (self, break); std :: util :: replace (self, Link (item, ~ tail)); 'Funkcje' replace' i 'swap' są ważnymi narzędziami podczas pracy z własnymi strukturami danych. – u0b34a0f6ae

Odpowiedz

5

przypisanie Albo od siebie (co moim zdaniem obejmuje budowę nowego coś z niego, jak w przypadku Link(item, *self)implies a move Oznacza to, że w procesie budowy nowego Link że samo staje się bezużyteczny, ponieważ:

"After a value has been moved, it can no longer be used from the source location and will not be destroyed there."

The Right Way ™ jest prawdopodobnie najlepiej udokumentowany przez co jest zrobione w this example in the stdlib. jest to podwójnie połączonej listy, i to udało, ale jest zmienny i mam nadzieję, skopiuj darmo. jest też list of useful container types też.

i udało się uzyskać niezmienną wersję Twoich danych struktura działa.

trait Stack<T> { 
    fn push(self, item : T) -> Self; 
    fn pop(self)   -> Option<(T, Self)>; 
    fn new()    -> Self; 
} 

#[deriving(Eq, ToStr)] 
enum Chain<T> { 
    Link(T, ~Chain<T>), 
    Break 
} 

impl<T> Stack<T> for Chain<T> { 
    fn push(self, item : T) -> Chain<T> { 
     Link(item, ~self) 
    } 
    fn pop(self)   -> Option<(T, Chain<T>)> { 
     match self { 
      Link(item, ~new_self) => Some((item, new_self)), 
      Break     => None 
     } 
    } 
    fn new()    -> Chain<T> { 
     Break 
    } 
} 

fn main() { 
    let b : ~Chain<int> = ~Stack::new(); 
    println(b.push(1).push(2).push(3).to_str()); 
} 
+1

To całkiem nieźle. Myślę, że gdybyś zmienił pop, by powrócić (Self, Option ) byłoby lepiej, ale to wielki krok we właściwym kierunku. Wielkie dzięki! –

+0

Sugestia podjęte. – tehgeekmeister

+3

Na tym etapie możesz równie dobrze ustawić opcję zawierającą oba wyniki - zawsze są one albo jedne, albo obydwa nieobecne. –