コンテンツにスキップ

最終更新:2026-10-12

C++ const ファミリー

目次

  • const
  • constexpr
  • C++20
  • consteval
  • constinit

注:本記事のすべてのコード例は星球に掲載しています。

1.const

const は C++/C を学ぶ際に最初に触れるキーワードのひとつで、通常は cv-qualifier として使われ、オブジェクトが不変であることを表します。**コンパイル時評価**は保証されず、いつ評価されるかはコンパイラが決定します。例えば:

const int a = 1; // 编译时
const auto x = getdata(); // 运行时

constはコンパイル時の定数式に使えることもありますが、例外もあります。例えば:

const double count_1 = 3.3;
std::array<double, static_cast<int>(count_1)> moreDoubles1 {1.1, 2.2, 3.3};

この場合、the value of 'count_1' is not usable in a constant expressionというエラーになります。

しかしこれは正常です:

const int count = 3;
std::array<double, count> doubles {1.1, 2.2, 3.3};

本質はコンパイル時の式評価にあります。そこでC++11ではconstexprが導入されました。

2.constexpr

constexprは、変数の値が定数式に現れることを指定できます。先ほどの例のconstをconstexprに変えるだけで、正常に動作します。

constexpr double count_2 = 3.3;
std::array<double, static_cast<int>(count_2)> moreDoubles2 {1.1, 2.2, 3.3}; 

constexpr は必ずしもコンパイル時にしか実行できないわけではありません。その本質的な意味は、コンパイル時に計算**できる**ということであり、実行時に constexpr 変数や関数を使えば、実行時に実行することもできます。

例えば:result1とresult2はまったく異なります。result1はコンパイル時に計算されますが、result2は実行時に計算されます。ちょっと疑問を投げかけましょう:なぜかわかりますか?

つまり、constexprを指定した関数が必ずコンパイル時に計算されるわけではありません。

constexpr int compileTimeSum(int a, int b) {
    return a + b;
}

int main() {
    constexpr int result1 = compileTimeSum(3, 5); 
    int x = 10;
    int result2 = compileTimeSum(x, 20);  
    return 0;
}

では、誰が保証してくれるのでしょうか?そこでC++20の登場です。

3.C++20

3.1 consteval

constevalは上の問題を解決します。関数にしか使えず、すべての呼び出しをコンパイル時に行うことを強制します。このとき上のconstexprをconstevalに変えると、result2はどうなるでしょうか?

それはエラーです:call to consteval function 'compileTimeSum(x, 20)' is not a constant expression

consteval int compileTimeSum(int a, int b) {
    return a + b;
}

int main() {
    constexpr int result1 = compileTimeSum(3, 5); 
    int x = 10;
    int result2 = compileTimeSum(x, 20);  
    return 0;
}

constevalを変数に対して使うと、これもエラーになります:error: a variable cannot be declared 'consteval'。

https://en.cppreference.com/w/cpp/language/consteval

3.2 constinit

constinitは静的またはスレッドローカル変数に定数初期化を強制できます。

  • constexpr、consteval と一緒には使えない
  • 非型指定子であり、その役割はassert
  • 変数が静的初期化されることを保証
  • static または thread_local にしか使えない

例えば:以下はコンパイルエラーになります:error: 'constinit' can only be applied to a variable with static or thread storage duration

constinit int a = 100;  
int main() {  
      ++a; 
      constinit auto b = 100;  // error
      // b has thread storage duration
      constinit thread_local auto b = 100;
}

関連トピック

コメント