4

ベクトルを繰り返し処理しても、ループ本体がベクトルを勝手に変更してはならないことは明らかです。これにより、バグが発生しやすいイテレータの無効化が防止されます。

ただし、すべての種類の突然変異が反復子の無効化につながるわけではありません。次の例を参照してください。

let mut my_vec: Vec<Vec<i32>> = vec![vec![1,2], vec![3,4], vec![5,6]];
for inner in my_vec.iter_mut() {        // <- or .iter()
    // ...
    my_vec[some_index].push(inner[0]);  // <-- ERROR
}

このような変更は のイテレータを無効にしませんがmy_vec、許可されていません。の特定の要素への参照が無効になる可能性がmy_vec[some_index]ありますが、いずれにしてもそのような参照は使用しません。

これらの質問がよくあることは承知しており、説明を求めているわけではありません。このループを取り除くことができるように、これをリファクタリングする方法を探しています。私の実際のコードでは、巨大なループ本体があり、これをうまく表現しないとモジュール化できません。

これまでに考えたこと:

  1. ベクトルを でラップしRc<RefCell<...>>ます。RefCellはイテレータによって借用され、ループ本体がそれを借用しようとすると失敗するため、これは実行時にまだ失敗すると思います。
  2. 一時的なベクトルを使用して将来のプッシュを蓄積し、ループの終了後にそれらをプッシュします。これは問題ありませんが、オンザフライでプッシュするよりも多くの割り当てが必要です。
  3. 安全でないコード、およびポインタのいじり。
  4. Iteratorドキュメントに記載されているものは役に立ちません。itertoolsをチェックアウトしましたが、どちらも役に立たないようです。
  5. while外側のベクトルへの参照を利用する反復子を使用する代わりに、ループとインデックスを使用します。これは問題ありませんが、イテレータとアダプタを使用できません。この外側のループを取り除き、 を使用したいだけですmy_vec.foreach(...)

これを適切に実行できるイディオムやライブラリはありますか? 安全でない関数は、ポインターを公開しない限り問題ありません。

4

2 に答える 2

3

のタイプを変更せずに、my_vecインデックスを作成してアクセスするだけで、次のように使用できますsplit_at_mut

for index in 0..my_vec.len() {
    let (first, second) = my_vec.split_at_mut(index);

    first[some_index].push(second[0]);
}

注: のインデックスはsecondだけずれていることに注意してくださいindex

これは安全で、比較的簡単で、非常に柔軟です。ただし、反復子アダプターでは機能しません。

于 2016-03-06T14:26:13.017 に答える
3

各内部ベクトルを でラップできますRefCell

use std::cell::RefCell;

fn main() {
    let my_vec : Vec<RefCell<Vec<i32>>> = vec![
        RefCell::new(vec![1,2]),
        RefCell::new(vec![3,4]),
        RefCell::new(vec![5,6])];
    for inner in my_vec.iter() {
        // ...
        let value = inner.borrow()[0];
        my_vec[some_index].borrow_mut().push(value);
    }
}

value参照するベクトルにプッシュできるようにする必要がある場合、ここでのバインディングが重要であることに注意してくださいinnervalueたまたま参照を含まない型 (それはi32) であるため、最初の借用をアクティブに保ちません (ステートメントの終わりまでに終了します)。次に、次のステートメントは、同じベクトルまたは別のベクトルを変更可能に借りることができ、機能します。

代わりに書いた場合my_vec[some_index].borrow_mut().push(inner.borrow()[0]);、ステートメントの最後まで両方の借用がアクティブになります。と の両方が同じmy_vec[some_index]inner参照する場合RefCell<Vec<i32>>、これは でパニックになりRefCell<T> already mutably borrowedます。

于 2016-03-06T05:24:26.910 に答える