Programmingバックエンド開発者

Rustにおけるさまざまな種類の参照について説明してください:可変参照と不変参照の違い、排他性とライフタイムのルール、さまざまな種類の参照を受け取る関数を書く方法について。構文の例を示し、参照の使用に関する一般的なエラーについて教えてください。

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

回答

Rustには2つの主な参照の種類があります:

  • 不変参照 (&T):読み取り専用のアクセスを提供します。
  • 可変参照 (&mut T):参照する値を変更することを可能にします。

ルール:

  • 同時に任意の数の不変参照、または1つの可変参照を持つことができ、同じスコープ内でこれを混在させることはできません。
  • 参照にはライフタイムがあり、コンパイル時に解析されます。

構文の例:

fn read(val: &i32) { println!("{}", val); } fn write(val: &mut i32) { *val += 1; } let mut x = 5; read(&x); write(&mut x);

トリッキーな質問

質問: 1つの関数の異なるスコープで同じ変数に2つの可変参照を作成できますか?

回答: いいえ、たとえ参照が異なるブロックで作成されても、借用解析のスコープは関数全体または変数全体をカバーし、コンパイラが参照が交差しないことを正確に証明できない場合です。これにより、コンパイルエラーが発生することがよくあります:

let mut x = 10; let r1 = &mut x; { let r2 = &mut x; // エラー! }

知識の欠如からくる実際のエラーの例


物語

パーサの開発中、開発者は読み取りと書き込みの最適化のために、同じバッファに可変参照と不変参照を同時に保持しようとしました。その結果、コードはコンパイルされず、unsafeでルールを「迂回」した後、データリークのバグが発生しました。


物語

データ処理プロジェクトの開始時に、参加者の1人がネストされたスコープを含む複雑なコードの「reanalyze borrow checker」を行いませんでした。その結果、参照の交差により、明示的な位置の指示がソースコードにない「cannot borrow as mutable because it's also borrowed as immutable」エラーが発生しました。


物語

マルチスレッドコードでは、共有データへのアクセスに通常の参照を使用しました。並行スレッドでデータを変更しようとすると、コンパイラの予期しないエラーや、unsafeコードを通じてborrow checkerを迂回する際のデータレースが発生しました。