387

次の定義に違いはありますか?

const     double PI = 3.141592653589793;
constexpr double PI = 3.141592653589793;

そうでない場合、C ++ 11ではどのスタイルが推奨されますか?

4

4 に答える 4

440

違いがあると思います。それらについてより簡単に話すことができるように、それらの名前を変更しましょう。

const     double PI1 = 3.141592653589793;
constexpr double PI2 = 3.141592653589793;

PI1とは両方ともPI2一定です。つまり、これらを変更することはできません。ただし、コンパイル時定数のみです。 コンパイル時に初期化され ますPI2。コンパイル時または実行時に初期化できます。さらに、コンパイル時定数を必要とするコンテキストでのみ使用できます。例えば:PI1 PI2

constexpr double PI3 = PI1;  // error

しかし:

constexpr double PI3 = PI2;  // ok

と:

static_assert(PI1 == 3.141592653589793, "");  // error

しかし:

static_assert(PI2 == 3.141592653589793, "");  // ok

どちらを使うべきですか?ニーズに合った方を使用してください。コンパイル時定数が必要なコンテキストで使用できるコンパイル時定数があることを確認しますか?実行時に行われる計算で初期化できるようにしたいですか?等。

于 2012-11-12T16:20:55.213 に答える
95

ここでは違いはありませんが、コンストラクターを持つ型がある場合は重要です。

struct S {
    constexpr S(int);
};

const S s0(0);
constexpr S s1(1);

s0は定数ですが、コンパイル時に初期化されることを約束するものではありません。s1がマークされconstexprているため、定数であり、Sのコンストラクタもマークされconstexprているため、コンパイル時に初期化されます。

これは主に、実行時の初期化に時間がかかり、その作業をコンパイラーにプッシュしたい場合に重要です。コンパイラーでも時間がかかりますが、コンパイルされたプログラムの実行時間が遅くなることはありません。

于 2012-11-12T16:04:41.647 に答える
64

constexprは、コンパイル中に一定で既知の値を示します。
constは、定数のみの値を示します。コンパイル中に知ることは必須ではありません。

int sz;
constexpr auto arraySize1 = sz;    // error! sz's value unknown at compilation
std::array<int, sz> data1;         // error! same problem

constexpr auto arraySize2 = 10;    // fine, 10 is a compile-time constant
std::array<int, arraySize2> data2; // fine, arraySize2 is constexpr

constオブジェクトはコンパイル中に既知の値で初期化する必要がないため、constはconstexprと同じ保証を提供しないことに注意してください。

int sz;
const auto arraySize = sz;       // fine, arraySize is const copy of sz
std::array<int, arraySize> data; // error! arraySize's value unknown at compilation

すべてのconstexprオブジェクトはconstですが、すべてのconstオブジェクトがconstexprであるとは限りません。

コンパイラに、コンパイル時定数を必要とするコンテキストで使用できる値が変数にあることを保証する場合、到達するツールはconstではなくconstexprです。

于 2015-01-22T10:06:48.390 に答える
20

constexprシンボリック定数には、コンパイル時に既知の値を指定する必要があります例えば:

constexpr int max = 100; 
void use(int n)
{
    constexpr int c1 = max+7; // OK: c1 is 107
    constexpr int c2 = n+7;   // Error: we don’t know the value of c2
    // ...
}

コンパイル時には不明であるが初期化後に変更されない値で初期化される「変数」の値を処理するために、C ++は定数の2番目の形式(const)を提供します。例えば:

constexpr int max = 100; 
void use(int n)
{
    constexpr int c1 = max+7; // OK: c1 is 107
    const int c2 = n+7; // OK, but don’t try to change the value of c2
    // ...
    c2 = 7; // error: c2 is a const
}

このような「<strong>定数変数」は、次の2つの理由で非常に一般的です。

  1. C ++ 98にはconstexprがなかったため、人々はconstを使用しました。
  2. 定数式ではない(コンパイル時に値がわからない)が、初期化後に値を変更しないリスト項目「変数」は、それ自体が広く役立ちます。

参照:Stroustrupによる「プログラミング:C++を使用した原則と実践」

于 2015-10-04T17:39:52.280 に答える