LoginSignup
4
2

More than 3 years have passed since last update.

constとconstexprについて

Posted at

はじめに

constconstexprについて、わかりづらかったので、記します。
アセンブリについて、実際に暑かったことはないので、誤解があるかもしれません。何かございましたらご指摘いただけたらと思います。

const

変数を定数とする修飾子。
const T name(Tにはintchar等, nameには変数名)のように宣言する。

const_example
int a = 10;
a = 5; // OK!

const int b = 10;
a = 5; // NG!

constexpr

コンパイル時定数の修飾子。上述のconstconstexpr(const exprではない)に書き換えるだけである。コンパイル時に決まっている値にしか用いることができない。
const T name(Tにはintchar等, nameには変数名)のように宣言する。
constでは、定数使用時にメモリにアクセスするのに対して、constexprはコンパイル事にソースコード内に埋め込まれるらしい。

const_example
int a = 10;
a = 5; // OK!

constexpr int b = 10;
a = 5; // NG!

本当?

ちょっと興味があり、アセンブリを見てみた(https://godbolt.org を使用)。コンパイラはx86-64 gcc 9.2

C++のソースコード 〜main内で宣言〜

intconst intconstexpr intをmain文で宣言して、三値を足すプログラムを書いた。
今までの自分のイメージだと、constexpr int cはメモリ確保せずにソースコード内で10という値として扱われるものだと考えていた。

main.cpp
int main()
{
    int a = 10;
    const int b = 10;
    constexpr int c = 10;

    int d = a + b + c;

    return 0;
}

アセンブリ

オプションなし

三値ともメモリ確保されているようである。(あれっ?)

main:
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-4], 10
        mov     DWORD PTR [rbp-8], 10
        mov     DWORD PTR [rbp-12], 10
        mov     eax, DWORD PTR [rbp-4]
        add     eax, 20
        mov     DWORD PTR [rbp-16], eax
        mov     eax, 0
        pop     rbp
        ret

オプション-O

変数を再利用していないため、最適化によってメモリ確保そのものが消えてしまった。

main:
        mov     eax, 0
        ret

ポインタに値を書き込むようにソースコードにint* p; *p = d;を追加すると、以下のようにあらかじめ和が算出された値で書き込まれていた。

main:
        mov     DWORD PTR ds:0, 30
        mov     eax, 0
        ret

C++のソースコード 〜main外で宣言〜

定数の宣言をグローバルで行い、メイン内で計算をしている。今まででは、constexprはメモリ確保されず、constはメモリ確保されると思っていた。

main.cpp
constexpr int a = 10;
const int b = 10;

int main()
{
    int c = a + b;
}

アセンブリ(オプションなし)

以下のように、定数は両者ともメモリ確保されておらず、代入ではあらかじめ和が算出された値となっていた。

main:
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-4], 20
        mov     eax, 0
        pop     rbp
        ret

おわりに

(最適化オプションなしにおける)constexprを少し誤解していたので、気づけてよかったなと思いました。コンパイラがすごく賢くてびっくりです。
ただ、今回は変数の再利用がなかったため最適化されているだけかもしれないので、引き続きconstexprを使おうと思います。ただし、できるだけグローバルで宣言しようと思います。

また、アセンブリについて、実際に暑かったことはないので、誤解があるかもしれません。何かございましたらご指摘いただけたらと思います。

4
2
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2