String::insert_str
は、文字列が本質的にVec<u8>
であるという事実を利用しています。それはreallocates the underlying buffer, moves all the initial bytes to the end, then adds the new bytes to the beginningです。
Vec
はもはや有効な状態になっていないため、通常は安全ではなく、直接Vec
に追加することはできません。データに「穴」があります。
データはu8
とu8
Drop
を実装していないので、これはString
のために重要ではありません。 Vec
に任意のT
の保証はありませんが、あなたの状態を追跡して適切にクリーンアップする場合は、同じことをすることができます - これはsplice
です。
先頭追加の全体のコンセプトは、一見
をexorcisedてきた私はVec
に先頭に追加すると、パフォーマンスの観点から、貧しい発想であるためであると仮定したいです。あなたがそれを行う必要がある場合は、ナイーブ場合は、ストレートフォワードです:
fn prepend<T>(v: Vec<T>, s: &[T]) -> Vec<T>
where
T: Clone,
{
let mut tmp: Vec<_> = s.to_owned();
tmp.extend(v);
tmp
}
我々はv
の2つのコピーのための十分なスペースを持っている必要がありますので、これは少し高く、メモリ使用量があります。
splice
メソッドは、新しい値のイテレータと置き換える値の範囲を受け入れます。この場合、何も置き換えたくないので、挿入するインデックスの空の範囲を指定します。我々はまた、適切な型のイテレータにスライスを変換する必要があります。
let s = &[1, 2, 3];
let mut v = vec![4, 5];
v.splice(0..0, s.iter().cloned());
splice
's implementation is non-trivialが、それは効率的に私たちに必要な追跡を行います。値の塊を取り除いた後、は、新しい値のためのメモリの塊を再利用します。また、ベクトルの末尾を(おそらく数回、入力イテレータに応じて)動かします。 Drop
の実装がSlice
の場合、常に有効な状態になります。
私は、データの先頭と末尾の両方の変更についてのより効率的に設計されていますようVecDeque
は、それをサポートしていないことが、より驚いています。Shepmasterが言ったことを考慮すると
は
[効率的の真ん中に複数の要素を挿入Vec](https://stackoverflow.com/questions/28678615/efficiently-insert-multiple-elements-in-the-middle-of-a-vec)? – trentcl
はい、prependingは特殊なケースです。 – user103185
@trentcl良い目!あなたは重複としてマークするべきだと思いますか? – Shepmaster