C ++ constexpr実現の違い

デニス・サブルコフ

constexpr関数について学び、コンパイラがコードを最適化する方法を知るためにgodbolt行き、コンパイラの動作がまったく異なることを発見しました。

次のコードがあります。

constexpr int square(int num) {
    return num * num;
}

int main() {
    int a = square(2);
}

g ++およびiccコンパイラーは関数の結果を計算し、それを変数に割り当てます(予想どおり)が、msvcおよびclangは関数を呼び出します。

最適化を使用するには、追加の手順を実行する必要があります。

constexpr int square(int num) {
    return num * num;
}

int main() {
    constexpr int c = square(2);
    int a = c;
}

そのような行動の合理的な説明はありますか?

godboltの例へのリンク:https://godbolt.org/z/ez7luu

max66

すべてのコンパイラは正しいです。

constexpr関数は、状況に応じて、コンパイル時または実行時に計算することができる機能です。

as-ifルールがないふりをすると、コンパイラは、関数の結果が既知のコンパイル時間であることが要求された場所に移動したときに、コンパイル時間を計算する必要があると言えconstexprます。

例として、配列のサイズ

int  a[square(10)];

またはテンプレートパラメータ

std::array<int, square(10)>  a;

またはconstexpr変数

constexpr int  a { square(10) };

実行時の既知の入力値を受け取る場合のように、関数を実行時に計算する必要がある状況があります。例によって

int a;

std::cin >> a;

int b { square(a) }; 

それ以外の場合、コンパイラは値をコンパイル時と実行時のどちらで計算するかを選択できます。

あなたの最初のバージョンでは

int a = square(2);

我々はので、コンパイラ-選択することができる領域である2コンパイラがコンパイル時計算を選択することができますので、コンパイル時に知られているが、値がないため、要求されたconstexprコンパイル時の値が必要ではないので、変数。

そして、2つのコンパイラがコンパイル時と他の2つのランタイムを計算していることがわかります。一般に、この種の動作は最適化レベルに大きく依存します。実際、例のコンパイルフラグに追加-O2した、すべてのコンパイラは異なる出力を生成します。

2番目のバージョンでは

 constexpr int c = square(2);

square()値が要求されconstexpr、可変なので、すべてのコンパイラは、しなければならない計算するsquare(2)(ので、彼らはそれを行うことができますコンパイル時に2コンパイル時に既知の値です)。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

C ++ 11constexpr互換性の実装

分類Dev

C ++での構造体の次の実装の違い

分類Dev

c# と php の抽象クラスの実装の違い

分類Dev

このconstexpr仮想関数手法はC ++ 11 / C ++ 14ルールに違反していますか?

分類Dev

std = c ++ 11とstd = gnu ++ 11のC ++標準正規表現の違い

分類Dev

C ++ 14の「constexpr」

分類Dev

C ++とCの違い&*

分類Dev

C ++ 17の静的constexpr変数と静的インライン変数の違いは何ですか?

分類Dev

C ++ 17の静的constexpr変数と静的インライン変数の違いは何ですか?

分類Dev

「if constexpr()」と「if()」の違い

分類Dev

「if constexpr()」と「if()」の違い

分類Dev

正規表現が異なるgrep-cとbcのパイプの違い

分類Dev

UDPネットワーク実装のCでのsend()とsendTo()の違い

分類Dev

cの2つのリンクリスト実装の違いを理解する

分類Dev

ReSharper C ++とVisualAssistの違い

分類Dev

c(...%*%...)とsum(... * ...)の違い

分類Dev

c(...%*%...)とsum(... * ...)の違い

分類Dev

SystemRootとC:\ Windowsの違い

分類Dev

C#とJavaのインターフェース実装の違い

分類Dev

C ++の標準ライブラリ実装の違いは何ですか?

分類Dev

SHA-1のC ++実装のハッシュが間違っています

分類Dev

CとC ++の静的初期化の違い

分類Dev

CでのStrcmp()関数の実現

分類Dev

VBとC#の実行順序に違いはありますか?

分類Dev

`constexpr`と` const`の違い

分類Dev

C ++ 14とC ++ 17の違い: `* p ++ = * p`

分類Dev

c99とc11の違い

分類Dev

「C ++ void Pointer」と「C#var」の違い

分類Dev

C型とC ++型の違い(typedef)

Related 関連記事

  1. 1

    C ++ 11constexpr互換性の実装

  2. 2

    C ++での構造体の次の実装の違い

  3. 3

    c# と php の抽象クラスの実装の違い

  4. 4

    このconstexpr仮想関数手法はC ++ 11 / C ++ 14ルールに違反していますか?

  5. 5

    std = c ++ 11とstd = gnu ++ 11のC ++標準正規表現の違い

  6. 6

    C ++ 14の「constexpr」

  7. 7

    C ++とCの違い&*

  8. 8

    C ++ 17の静的constexpr変数と静的インライン変数の違いは何ですか?

  9. 9

    C ++ 17の静的constexpr変数と静的インライン変数の違いは何ですか?

  10. 10

    「if constexpr()」と「if()」の違い

  11. 11

    「if constexpr()」と「if()」の違い

  12. 12

    正規表現が異なるgrep-cとbcのパイプの違い

  13. 13

    UDPネットワーク実装のCでのsend()とsendTo()の違い

  14. 14

    cの2つのリンクリスト実装の違いを理解する

  15. 15

    ReSharper C ++とVisualAssistの違い

  16. 16

    c(...%*%...)とsum(... * ...)の違い

  17. 17

    c(...%*%...)とsum(... * ...)の違い

  18. 18

    SystemRootとC:\ Windowsの違い

  19. 19

    C#とJavaのインターフェース実装の違い

  20. 20

    C ++の標準ライブラリ実装の違いは何ですか?

  21. 21

    SHA-1のC ++実装のハッシュが間違っています

  22. 22

    CとC ++の静的初期化の違い

  23. 23

    CでのStrcmp()関数の実現

  24. 24

    VBとC#の実行順序に違いはありますか?

  25. 25

    `constexpr`と` const`の違い

  26. 26

    C ++ 14とC ++ 17の違い: `* p ++ = * p`

  27. 27

    c99とc11の違い

  28. 28

    「C ++ void Pointer」と「C#var」の違い

  29. 29

    C型とC ++型の違い(typedef)

ホットタグ

アーカイブ