はじめに
Rust を学び始めると、最初に出会うのが『変数の宣言』です。
Rust では変数を宣言するために、let 、let mut 、const 、static 、
といったキーワードが用意されています。
他の言語でも用意されている予約語ですが、それぞれ役割や使いどころが異なります。
本記事では、これらのキーワードの違いや使い分けについて、わかりやすく解説していきます。
初めて Rust に触れる方でも理解しやすいように、具体的なコード例を交えて紹介します。
こんな疑問をもった方におすすめ
- なぜ let と const が両方あるの?
- mut って何?
- static っていつ使うの?
letとlet mut:値の可変性とシャドーイング
let:不変な変数
|
1 2 3 4 5 6 7 |
fn main() { let x = 5; println!("x = {}", x); // x = 6; // コンパイルエラー:xは不変 } |
let で宣言された変数は一度値を代入したら変更できません。
これにより、予期しない値の変更をコンパイル時に防ぎ、安全性を高めています。
let mut:可変な変数
|
1 2 3 4 5 6 7 8 |
fn main() { let mut x = 5; println!("x = {}", x); x = 6; // OK println!("x = {}", x); } |
mut を付けることで、変数の値を変更可能にできます。
とはいえ、無闇に可変にするのではなく、本当に必要な場面でのみ使うのが Rust らしいスタイルです。
シャドーイング
Rustでは、同じ名前の変数を再定義する(シャドーイング)こともできます。
|
1 2 3 4 5 6 |
fn main() { let x = 5; let x = x + 1; // 新しいxが作られる println!("x = {}", x); // x = 6 } |
let は再定義によって新しい変数として扱われるため、「不変性」と「値の更新」の両立ができます。
constとstatic:定数とグローバル定数
const と static は、どちらも定数を宣言するために使われますが、役割やスコープに違いがあります。
const:コンパイル時定数
|
1 2 3 4 5 6 |
const PI: f64 = 3.1415; fn main() { println!("円周率: {}", PI); } |
- const は関数の外でも中でも使える定数
- 値はコンパイル時に完全に決まっている必要があり
- 必ず型注釈が必要
- 値はインライン展開され、スコープは広いが、スレッドローカル
static:静的変数(グローバルスコープ)
|
1 2 3 4 5 6 |
static HELLO: &str = "Hello, world!"; fn main() { println!("{}", HELLO); } |
- static はプログラムの全期間で有効なグローバル変数
- メモリに一度だけ割り当てられ、永続的に保持
- ミュータブルな static は unsafe になる
|
1 2 3 4 5 6 7 8 9 |
static mut COUNTER: u32 = 0; fn main() { unsafe { COUNTER += 1; println!("COUNTER = {}", COUNTER); } } |
注意ポイント
static mut はグローバルな可変変数ですが、データ競合のリスクがあるため、
unsafe ブロックが必要になります。
まとめ表
| キーワード | 再代入可否 | スコープ | メモリ保持 | 型注釈 | 特徴 |
| let | 不可 | ローカル | 一時的 | 任意 | 基本的な変数宣言 |
| let mut | 可能 | ローカル | 一時的 | 任意 | 可変性が必要な場合に使用 |
| const | 不可 | グローバル/ローカル | コンパイル時 | 必須 | 高速で安全な定数 |
| static | 不可 | グローバル | 永続 | 必須 | 静的ライフタイムを持つ |
| static mut | 可能 | グローバル | 永続 | 必須 | 静的ライフタイムを持つ |
おわりに
Rust の変数宣言には、意図的な設計が詰まっています。
let と let mut で可変・不変を明確にし、const と static で定数の使い分けができます。
初めは少し戸惑うかもしれませんが、使い分けに慣れると、コードの意図がより明確になり、
安全で読みやすいプログラムを書けるようになります。
ぜひ、実際に手を動かして試してみてください!