2016-12-08 5 views
0

バイナリツリーを実装します。Rcでバイナリツリーを実装するときに不変の借用したコンテンツを変更可能なものとして借りることはできません

error: cannot borrow immutable borrowed content as mutable 
    --> so.rs:31:9 
    | 
31 |   root.insert_left(&left); 
    |   ^^^^ 

error: aborting due to previous error 

私はここで間違っているものを理解することはできません:私はコンパイルエラーを持っている

use std::rc::Rc; 

struct Node { 
    left: Option<Rc<Node>>, 
    right: Option<Rc<Node>>, 
    data: String, 
} 


impl Node { 
    fn new(_data: String) -> Node { 
     Node { 
      data : _data.clone(), 
      left : None, 
      right : None, 
     } 
    } 

    fn insert_left(&mut self, mut node: &Rc<Node>) { 
     self.left = Some(node.clone()); 
    } 

    fn insert_right(&mut self, mut node: &Rc<Node>) { 
     self.left = Some(node.clone()); 
    } 
} 

fn main() { 
    let mut root = Rc::new(Node::new(String::from("root"))); 
    let mut left = Rc::new(Node::new(String::from("left"))); 
    root.insert_left(&left); 
} 

:コードはおそらく慣用錆はありませんが、次のコードをコンパイルするように、私の主な言語はC++です。いくつかの試行錯誤の反復の後で、私は問題がinsert_left()関数にあることを発見しました。selfが不変参照であれば、それはコメントアウトされた内容でコンパイルされますが、不変の参照は私の目標を達成できません。ここで

+2

あなたは[** 23の他の質問と同じエラーメッセージ**]を見ましたか(http://stackoverflow.com/search?q=is%3Aq+cannot+borrow+immutable+borrowed+content+as +変更可能)? *これらの質問と異なる点は何ですか?関連性が高いと思われる[Rustのツリー内のノードを変更する](http://stackoverflow.com/q/28008585/155423)というタイトルもあります。 (質問メーリングリストからの努力は大変です)(http://meta.stackoverflow.com/q/261592/155423)、少なくとも同じエラーメッセージとデータ構造を持つ他の質問を見つけることは最低限のようです。 – Shepmaster

+1

慣用錆については、変数 '_data'を呼ぶべきではありません。先行するアンダースコアは、未使用の変数*を示すために使用されます。その変数は非常に多く使われています。 – Shepmaster

+0

@Shepmaster関数を構築するための入力引数のためのより良い規則は何ですか? – Alex

答えて

6

はあなたの問題のMCVEです:

use std::rc::Rc; 

struct Node; 

impl Node { 
    fn insert_left(&mut self) {} 
} 

fn main() { 
    let root = Rc::new(Node); 
    root.insert_left(); 
} 

あなたはまだ同じエラーを取得しながら、できるだけ多くのコードを削除することによって、このような例に到着することができます。このプロセスは、問題の理解を深めるのに大いに役立ちます。

Rcはどのような種類の変異も許可しないという問題があります。 stated in the documentationとして:

Shared pointers in Rust disallow mutation by default, and Rc is no exception. If you need to mutate through an Rc , use Cell or RefCell .

したがって、insert_leftメソッドを呼び出すために必要とされるであろう&mut FooRc<Foo>から行く方法はありません。

文書として、あなたはCellRefCellなど内部可変性を可能にするタイプのいずれか、使用することができます。これらはミューテックスのように少し機能しますが、マルチスレッドのシナリオでは有効ではありません。 Rustの安全性の重要な要素である、値に対する変更可能な参照は一度に1つしか使用できないことを保証します。

Rcの機能が必要ない場合は、Option<Box<Node>>に移動するだけで済みます。

関連する問題