【C# / C++】const / constexpr とは何か。「定数」以上の意味を解説

C#

C# の次世代バージョン(C# 10.0?)で、const として定義できる変数の範囲が広がるようです。

このような例は、今までのバージョンでは const ではなく static readonly としてのみ定義できました。
これでも「コード上で値が変わらない」という意味での「定数」としては機能していました。

では、「const と static readonly って何が違うの?」と問われると、「const はコンパイル時定数で、static readonly は実行時定数である」が答えになります。

ちなみに、C++ では明示的にコンパイル時定数として扱いたい変数は constexpr という予約語を使います。
C# / C++ 共に、コンパイル時定数・実行時定数という概念は共通です

この記事ではその違いについて解説します。

そもそも「コンパイル」って?

コンパイルとは、プログラムを実行ファイル(Windows における exe)や中間コードに変換することを指します。

C# や C++ などのプログラミング言語によって書かれたプログラムは、人にとって読みやすいファイルと言えます。
ただ、このプログラムはコンピュータが理解することは難しい形式になっています。

多くの人が「コンピュータは 0 と 1 しか理解できない」といったことを聞いたことがあると思います。
では、なぜプログラムによってコンピュータを動かせるのかと言うと、プログラムをコンピュータが理解できるような 0 / 1 の文字列に置き換えているからです。
そして、この「置き換える作業」こそがコンパイルと呼ばれている工程です。

とは言っても、今までプログラミングをしたことのある人からすれば、「そんな面倒くさそうなこと、やった覚えは無いよ?」という意見が出てきそうです。
実はコンパイルは人間が手でやることではなく、言語ごとにそれ用のソフトウェアが用意されています
そして、プログラムを書く人がコンパイルを特別意識する必要がないようにデザインされているのです。
例えば、Visual Studio ではビルドというコマンドの中でコンパイルが行われています。

「コンパイル時定数」と「実行時定数」の違い

では、本題である「コンパイル時定数」と「実行時定数」の違いについて解説します。

コンパイル時定数は、コード(プログラム)をコンパイルした時点で定数化されます
つまり、コンパイルの結果である実行ファイルや中間コードに、計算結果の値がそのまま埋め込まれるという定数なのです。

一方、実行時定数は、プログラムを実行した初めに値が計算され、その結果が不変値となるという定数です。
そのため、コンパイルの結果である実行ファイル・中間コードには計算結果が埋め込まれません。

どちらも、プログラム上では「不変の値」として扱うことができる点で同じです。
では、何が違ってくるか(どちらも使えるような状況で、どう使い分ければいいか)と言いますと、主に動作速度プログラムの柔軟性が変わってきます。

まず動作速度ですが、コンパイル時定数の場合、実行時には結果をただ読み込むだけです。
そのため、余計な計算をする必要がないのでコンパイル時定数の方が速くなります

一方、コンパイル結果に値が埋め込まれるということは、値を変えたい場合に必ずコンパイルが必要になる、ということです。
つまり、環境によって適切な値が変わるような定数は、環境ごとにコンパイルが必要になってきます(参考: const のバージョニング問題)。
しかし、実行時定数の場合は実行時に値が決定されるため、コンパイルが必要になりません。
この点で、プログラムの柔軟性は実行時定数の方に軍配が上がります

まとめ

  • 「定数」には「コンパイル時定数」と「実行時定数」があります。
  • 動作速度を気にする場合は、コンパイル時定数が適切です。
  • プログラムの柔軟性を気にする場合は、実行時定数が適切です。

コメント

タイトルとURLをコピーしました