C/C++では定数を定義するためのいくつかの異なる方法がある。
方法 | コンパイル時定数? | アドレス取得可能? | その他 |
---|---|---|---|
const |
△ | Y | |
static const |
△ | Y | |
constexpr |
Y | Y | C++11から |
#define |
△ | N | 単純置換 型無し |
enum |
Y | N | 整数定数のみ 内部型は実装依存(※) |
(※) enum
はC++11から内部で使用する整数型を自分で決められるようになった。
#コンパイル時定数?
コンパイル時定数でないと、テンプレートパラメータや配列宣言時の要素数指定として使えない。
const
、static const
、#define
はどのように初期化・宣言するかによってコンパイル時定数かどうかが異なる。
// f() は定数表現でないものとする
const int a = f(); // OK コンパイル時定数ではない
static const int b = f(); // OK コンパイル時定数ではない
constexpr int c = f(); // NG 定数表現でしか初期化できない
#define d f() // OK コンパイル時定数ではない
enum { e = f() }; // NG 整数定数表現でしか初期化できない
しかし、この3つもリテラルなどの定数表現で初期化・宣言すればコンパイル時定数として扱える。
確実にコンパイル時定数であることが保証されるのはconstexpr
とenum
だけである。
#アドレス取得可能?
変数はアドレスを持っているものだが、#define
とenum
は変数ではないから、アドレスを持たない。