Programmingバックエンド開発者

Rustにおける定数と静的変数は何ですか?それぞれの違いと、それぞれを使用する際の好ましいケースは何ですか?

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

答え

Rustには、プログラム実行中に不変のデータを保持するための主な方法としてconststaticの二つがあります。

**定数(const)**は、コンパイル時に計算される不変の値です。常に明示的に型指定され、定数式で初期化される必要があります(これはコンパイル時に計算可能なものです)。定数はメモリ内の固定アドレスを持たず、コンパイラによって使用場所に「挿入」されます。

const MAX_ATTEMPTS: u32 = 5;

**静的変数(static)**は、プログラム実行中に特定のメモリ領域に値を保持します。そのアドレスは固定されており、変更可能(static mutを使用)ですが、多スレッドシナリオではデータ競合の可能性があるため、特別な注意が必要です。

static APP_NAME: &str = "MyApp"; static mut COUNTER: u32 = 0;
  • constを使用するのは、値がコンパイル時に常に知られている必要があり、グローバルストレージが必要ない場合です。
  • staticを使用するのは、全てのモジュールがアクセスするための単一のストレージ場所が必要であるか、または値がコンパイル時に計算できない場合です。

トリック質問

Rustにおけるconststaticの違いは何ですか?静的変数は非定数を参照できますか?

答え: 主な違いはストレージの範囲(ライフタイム)です:constはメモリ内の存在を保証しません(これは値の置換です)、staticはプログラム全体にわたって生存するオブジェクトで、固定アドレスを持ちます。

静的変数には、コンパイル時に知られている値のみを代入することができます:

let a = 42; // static INVALID: i32 = a; // エラー!定数のみが許可されます。

このテーマの細かい違いを知らなかったことによる実際のエラーの例。


物語

負荷分散のバックエンドサービスのプロジェクトで、開発者の一人が異なるスレッドからの共有カウンターのためにstatic mutを使用し、同期を行いませんでした。これによりデータ競合が発生し、予測不能な結果をもたらしました — 一部のリクエストが単に失われました。解決策は、std::sync::atomicの原子型を使用すること、またはMutexを使用することです。


物語

若手開発者がユーザーの挨拶文をconstを使って定数にしたが、初期化中に計算される関数の結果に合わせようとしました。コンパイラはエラーを出しました。この値はコンパイル時に定義されている必要があるからです。理由は、定数はコンパイル時に計算可能でなければならないのに対して、関数は実行時に値を返すからです。


物語

古いプロジェクトで、すべてのグローバル値をstaticに置き換えましたが、文字列リテラルがプログラムのメモリ範囲を使用することを忘れ、一部の宣言は実際には値の置換のみを必要としていました:これによりバイナリのサイズが増加し、メモリ管理が複雑になりました。その結果、起動時間の増加とライブラリの動的読み込み時のリークが発生しました。