constとconstexprの違い

5796 ワード

const
  • オブジェクトの定数は、物理定数(すなわち、bitごとに変更できない)と論理定数(すなわち、オブジェクトの表現が変わらない)の2つに分けられます.C++には、物理定数(例えば、
  • )が採用されています.
    struct A {
        int *ptr;
    };
    int k = 5, r = 6;
    const A a = {&k};
    a.ptr = &r; // error
    *(a.ptr) = 7; // no error
    
  • aがconstオブジェクトである場合、aの任意のメンバーに値を割り当てることはerrorとみなされますが、ptrを変更せずにptrが指すオブジェクトを変更すると、コンパイラはエラーを報告しません.これは実際に論理定数性に反しています.Aの表現が変わったからです.

  • constexpr
  • constexprはC++11に追加されたキーワードであり、その意味は「定数式」、すなわちコンパイル期間中に評価可能な式である.最も基本的な定数式は、文字値やグローバル変数/関数のアドレスやsizeofなどのキーワードが返す結果であり、他の定数式は、基礎式が様々な決定された演算によって得られる.constexpr値はenum,switch,配列長などに用いることができる.
  • constexprで修飾された変数は必ずコンパイル期間で評価可能であり、修飾された関数はそのすべてのパラメータがconstexprである場合、必ずconstexprを返す.
  • constexpr int Inc(int i) {
        return i + 1;
    }
    
    constexpr int a = Inc(1); // ok
    constexpr int b = Inc(cin.get()); // error
    constexpr int c = a * 2 + 1; // ok
    
  • constexprは、クラスの構造関数を修飾するためにも使用できます.すなわち、その構造関数に提供されるパラメータがconstexprである場合、生成されたオブジェクトのすべてのメンバーがconstexprであることを保証します.このオブジェクトはconstexprオブジェクトであり、constexprしか使用できない場合に使用できます.注意:constexprコンストラクション関数のすべてのメンバー変数の初期化は初期化リストに格納されます.
  • struct A {
        constexpr A(int xx, int yy): x(xx), y(yy) {}
        int x, y;
    };
    constexpr A a(1, 2);
    enum {SIZE_X = a.x, SIZE_Y = a.y};
    

    constexprのメリット:
  • は、プログラムの正確な意味が破壊されないことをよりよく保証する強い制約である.
  • コンパイラは、使用するconstexpr式を直接最終結果に置き換えるなど、コンパイル期間中にconstexprのコードを非常に大きく最適化することができる.
  • マクロに比べて、追加のオーバーヘッドはありませんが、より安全で信頼性があります.