2016-08-10 5 views
1

私は錆に慣れていて、私は借用チェッカーにいくつか問題があります。なぜこのコードがコンパイルされないのか分かりません。申し訳ありませんが、これは以前に答えられた質問に近いですが、私が見た他の質問で解決策を見つけることができないようです。文字列スライスのベクトルを返すことができません:借りた値が十分に長く生きていません

私はReturn local String as a slice (&str)との類似点を理解していますが、その場合はただ1つの文字列が返され、ベクターを返そうとしている私のコードで私が推論するのに十分ではありません。私が理解したところでは、私はstr型への参照を返すようにしています。これは、関数ブロックの最後にスコープから外れるので、&strのベクトルをStringのベクトルにマッピングする必要がありますか?私は、&strStringに変換することによるパフォーマンスの影響については心配していません。まず、私はそれを働かせたいです。

これはコードです。エラーはlex機能にあります。ここで

use std::io::prelude::*; 
use std::fs::File; 
use std::env; 

fn open(mut s: &mut String, filename: &String) { 
    let mut f = match File::open(&filename) { 
     Err(_) => panic!("Couldn't open file"), 
     Ok(file) => file, 
    }; 
    match f.read_to_string(&mut s) { 
     Err(_) => panic!("Couldn't read file"), 
     Ok(_) => println!("File read successfully"), 
    }; 

} 

fn lex(s: &String) -> Vec<&str> { 
    let token_string: String = s.replace("(", " (") 
     .replace(")", ") "); 

    let token_list: Vec<&str> = token_string.split_whitespace() 
     .collect(); 
    token_list 
} 

fn main() { 
    let args: Vec<_> = env::args().collect(); 
    if args.len() < 2 { 
     panic!("Please provide a filename"); 
    } else { 
     let ref filename = args[1]; 

     let mut s = String::new(); 
     open(&mut s, filename); 
     let token_list: Vec<&str> = lex(&s); 
     println!("{:?}", token_list); 
    } 
} 

は錆の経験の私のレベルで、私はこれらの変数の寿命を視覚化することができないので、私はそれは難しい、このコードを理由に探していたエラーメッセージ

error: borrowed value does not live long enough 
     self.0.borrow().values.get(idx) 
     ^~~~~~~~~~~~~~~ 
reference must be valid for the anonymous lifetime #1 defined on the block at 23:54... 
    pub fn value(&self, idx: usize) -> Option<&Value> { 
                ^
note: ...but borrowed value is only valid for the block at 23:54 
    pub fn value(&self, idx: usize) -> Option<&Value> { 
                ^

です。私はこれを理解しようと1〜2時間を費やしたので、どんな助けにも感謝します。

+3

他の「xは十分に長くは生きていません」というスタックオーバーフローの質問を見たことがありますか? 'lex'関数に新しい' String'を作成し、その 'String'が' lex'関数よりも古くても参照を返すようにしています。 –

+0

関数外の文字列を定義して、可変参照を渡す必要がありますか、関数内で定義された文字列の寿命を延長して 'lex'関数よりも長生きできる方法はありますか? –

+1

あなたは永遠に生涯を延長することはできません。私はあなたの問題に対する解決策を持っていますが、重複としてマークしたくない場合は、質問を変更する必要があります。それは所有されたオブジェクトへの参照を返す方法を尋ねる他のすべての質問とは異なる理由を扱うべきです。 –

答えて

0

問題は、あなたがlex関数の中で新しいStringtoken_string)を割り当て、それへの参照の配列を返すしているということですが、できるだけ早くそれが外に落ちるようtoken_stringが落とされます(とメモリが解放されました)スコープは関数の最後にあります。

fn lex(s: &String) -> Vec<&str> { 
    let token_string: String = s.replace("(", " (") // <-- new String allocated 
     .replace(")", ") "); 

    let token_list: Vec<&str> = token_string.split_whitespace() 
     .collect(); 
    token_list // <-- this is just an array of wide pointers into token_string 
} // <-- token_string gets freed here, so the returned pointers 
    //  would be pointing to memory that's already been dropped! 

これに対処する方法はいくつかあります。 1つは、lexの呼び出し元に、収集に使用するバッファーを渡すことです。これは、この署名が返さ&str秒の寿命が渡されたのバッファの寿命と少なくとも同じ長さになることを指定しますfn lex<'a>(input: &String, buffer: &'a mut String) -> Vec<&'a str>に署名を変更します。

もう一つの方法は、単にVec<String>を返す代わりにすることです余分な割り当てを許容できる場合はVec<&str>です。

+0

ご協力ありがとうございます。それは今、多くの意味があります。 –

関連する問題