`const` と `static`

Rustでは const を用いることで定数を定義することができます:

fn main() { const N: i32 = 5; }
const N: i32 = 5;

let による束縛とは異なり、const を用いるときは型を明示する必要があります。

定数はプログラム全体のライフタイムの間生きています。 さらに言えば、Rustプログラム中で定数はメモリ中に固定のアドレスを持ちません。 これは定数が利用されている時にそれらが効率的にインライン化されるためです。 このため、同じ定数への参照が必ずしも同じアドレスを指しているとは保証されません。

static

Rustは「グローバル変数」と呼ばれる静的アイテムを提供します。 「グローバル変数」は定数と似ていますが、静的アイテムは使用にあたってインライン化は行われません。 これは、「グローバル変数」にはそれぞれに対しただひとつのインスタンスのみが存在することを意味し、 メモリ上に固定の位置を持つことになります。

以下に例を示します:

fn main() { static N: i32 = 5; }
static N: i32 = 5;

let による束縛とは異なり、static を用いるときは型を明示する必要があります。

静的アイテムはプログラム全体のライフタイムの間生きています。 そのため定数に保存されている参照は static ライフタイムを持ちます:

fn main() { static NAME: &'static str = "Steve"; }
static NAME: &'static str = "Steve";

ミュータビリティ

mut を利用することでミュータビリティを導入することができます:

fn main() { static mut N: i32 = 5; }
static mut N: i32 = 5;

この静的な変数 N はミュータブルであるため、別のスレッドから読まれている間に変更される可能性があり、メモリの不安全性の原因となります。 そのため static mut な変数にアクセスを行うことは unsafe であり、 unsafe ブロック中で行う必要があります。

fn main() { static mut N: i32 = 5; unsafe { N += 1; println!("N: {}", N); } }

unsafe {
    N += 1;

    println!("N: {}", N);
}

さらに言えば、 static な変数に格納される値の型は Sync を実装しており、 かつ Drop は実装していない必要があります。

初期化

conststatic どちらも値に対してそれらが定数式でなければならないという要件があります。 言い換えると、関数の呼び出しのような複雑なものや実行時の値を指定することはできないとうことです。

どちらを使うべきか

大抵の場合、staticconst で選ぶときは const を選ぶと良いでしょう。 定数を定義したい時に、そのメモリロケーションが固定であることを必要とする場面は珍しく、 const を用いることで定数伝播によってあなたのクレートだけでなく、それを利用するクレートでも最適化をすることができます。