ProgrammingRust開発者

Rustにおけるコレクション(例えば、VecやHashMap)の取り扱いはどのようになっているのか?所有権の特徴は何か、また、要素やコレクションをクローンする必要があるのはいつか?

Hintsage AIアシスタントで面接を突破

回答

Rustの標準コレクション(例:Vec<T>、HashMap<K,V>、HashSet<T>など)は、内容の所有権の原則を実装しています。これは、コレクションがそのすべてのオブジェクトを所有し、削除時にメモリの解放を担当することを意味します。

例えば、Vec<T>に入れられた要素はベクターに移動し(move)、その後そのベクターがそれらを所有します:

let s = String::from("hi"); let mut v = Vec::new(); v.push(s); // sは移動され、もはやアクセスできません

コレクションがコピー可能な値を含む場合、それらはコピーされます。移動可能な場合は、所有権が移譲されます。要素やコレクションをクローンする必要があるのは、元の値を2つの場所に保持したい場合です。例えば:

let name = String::from("Olga"); let mut v = Vec::new(); v.push(name.clone()); println!("{}", name); // nameはクローンされたため、依然としてアクセス可能です

誤解を招く質問

HashMapに要素を挿入する際に、移動可能なデータ型(例えば、String)をキーとして使用すると、挿入後に元のキーはアクセス可能ですか?

しばしば誤った答えが与えられます:「元のキーは挿入後もアクセス可能です」。

実際には、キーと値の所有権がHashMapに移り、挿入後は前もってクローンしない限り、使用できません:

let key = String::from("id"); let mut map = std::collections::HashMap::new(); map.insert(key, 42); // keyはもはやアクセスできません

keyにアクセスしようとすると、コンパイルエラーが発生します。

このトピックに関する実際のエラーの例


物語 開発者がVecに挿入後に移動したオブジェクトを使用しようとし、「value used here after move」というエラーに直面し、Vectorがそれを所有していることを理解できませんでした。


物語 HashMapを操作する際、文字列キーをクローンし忘れたため、他の場所で使用できなくなり、コードの大規模なリファクタリングが必要になりました。


物語 プロジェクトの一つで、関数の外でベクターの内部要素への参照を返そうとし、ベクターのサイズ変更時にその参照が無効になることを忘れたため、ダングリング参照が発生し、実行中にクラッシュしました(panic)。