web-dev-qa-db-ja.com

ベクトルにスライスを追加する慣用的な方法は何ですか?

&[u8]のスライスがあり、Vec<u8>に最小限のコピーで追加したいと思います。ここに私が知っている2つのアプローチがあります:

let s = [0u8, 1u8, 2u8];
let mut v = Vec::new();
v.extend(s.iter().map(|&i| i));
v.extend(s.to_vec().into_iter()); // allocates an extra copy of the slice

Rust stable?(rustc 1.0.0-beta.2)でこれを行うより良い方法はありますか?

26
Kai

まさにこれを行うメソッドがあります: Vec::extend_from_slice

例:

let s = [0u8, 1, 2];
let mut v = Vec::new();
v.extend_from_slice(&s); 
45
heinrich5991
_v.extend(s.iter().cloned());
_

これは.map(|&i| i)を使用するのと実質的に同等であり、最小コピーを行います。

問題は絶対にcannotこの場合コピーを避けることです。スライスその内容を所有していないであるため、単純に値を移動することはできません。したがって、コピーしか取得できません。

そうは言っても、考慮すべきことが2つあります。

  1. Rustはかなり積極的にインライン化する傾向があります。このコードには、中間ステップなしで値を宛先に直接コピーするのに十分な情報がコンパイラにあります。

  2. Rustのクロージャーは、他のほとんどの言語のクロージャーとは異なります。ヒープ割り当てを必要とせず、直接インライン化できるため、動作を直接ハードコーディングするよりも効率的です。

上記の2つは最適化に依存していることを忘れないでください。通常は最適な結果が得られますが、保証はされません。


しかしそれを言った...あなたが実際にここでやろうとしていること特定例はあなたがスタックに割り当てられた配列を追加するdo =自分のもの。私はこの事実を実際に活用できるライブラリコードを知りません(Rust)では配列値のサポートはかなり弱いですが)、理論的には、into_iter()安全でないコードを使用した場合と同等...しかし、私はそれをお勧めしません。おそらく面倒の価値はありません。

14
DK.

完全なパフォーマンスへの影響について話すことはできませんが、v + &sはベータ版で動作しますが、これは各値を元のVecにプッシュするのに似ていると思います。

2
kbknapp