Constexpr variable evaluation

删除回忆录丶 提交于 2019-12-05 02:57:03

问题


Here is my code and I need clarification on what's happening:

constexpr int funct(int x){
    return x + 1;
}


int main(){
    int x = funct(10);
    return 0;
}

constexpr's allows compile time calculation, and based on my code above, since funct is declared as constexpr, it is allowed to do compile time calculations if the arguments are constants or constexpr's themselves.

The part that I am confused with lies in this part, the int x. Since it is not declared as constexpr, would it mean that int x will get the value at runtime? Does that mean that declaring it to be constexpr int x will mean that int x will get the value at compile time unlike int x ?


回答1:


It depends on the compiler in question on many counts. What sorts of optimizations that may take place, etc. However, constexpr does not inherently enable compile-time calculations.

Take this code:

#include <cstdio>

constexpr int test(int in)
{
   return in + 25;
}

int main(int argc, char* argv[])
{
   printf("Test: %u\n", test(5));
   printf("Two: %u\n", test(10));
}

Under GCC 4.8.4 on my x86_64 Gentoo box, that actually still makes a call on both counts to the supposedly compile-time "test". The lines I used were

g++ -std=c++11 -Wall -g  -c main.cpp -o obj/Debug/main.o
g++  -o bin/Debug/TestProject obj/Debug/main.o   

So on the code above, that produces the following machine code:

0x40061c    mov    edi,0x5
0x400621    call   0x400659 <test(int)>
0x400626    mov    esi,eax
0x400628    mov    edi,0x4006f4
0x40062d    mov    eax,0x0
0x400632    call   0x4004f0 <printf@plt>
0x400637    mov    edi,0xa
0x40063c    call   0x400659 <test(int)>
0x400641    mov    esi,eax
0x400643    mov    edi,0x4006fd
0x400648    mov    eax,0x0
0x40064d    call   0x4004f0 <printf@plt>

Where the asm block for "test" is:

0x400659    push   rbp 
0x40065a    mov    rbp,rsp
0x40065d    mov    DWORD PTR [rbp-0x4],edi
0x400660    mov    eax,DWORD PTR [rbp-0x4]
0x400663    add    eax,0x19
0x400666    pop    rbp
0x400667    ret

So, as you can see in that situation, it seems to hold pretty much no effect over how GCC produced that code. Even if you do this, you will still get runtime calculations:

int value = test(30);
printf("Value: %u\n", value);

Where that produces this (the address of test changed slightly due to adding some more code):

0x40061c    mov    edi,0x1e
0x400621    call   0x40067a <test(int)>
0x400626    mov    DWORD PTR [rbp-0x4],eax
0x400629    mov    eax,DWORD PTR [rbp-0x4]
0x40062c    mov    esi,eax
0x40062e    mov    edi,0x400714
0x400633    mov    eax,0x0
0x400638    call   0x4004f0 <printf@plt>

It does, however, produce the expected result if you declare the value itself as constexpr:

constexpr int value = test(30);
printf("Value: %u\n", value);

And the associated code is:

0x400623    mov    esi,0x37
0x400628    mov    edi,0x400714
0x40062d    mov    eax,0x0
0x400632    call   0x4004f0 <printf@plt>

So essentially, you're not guaranteed a compile-time calculation if you simply prepend the method declaration with constexpr. You also need to declare your a variable as constexpr and assign to it. Doing such a declaration will actually require the compiler to statically evaluate the result. GCC actually yells at you if you try to do this and "test" isn't declared constexpr:

main.cpp|10|error: call to non-constexpr function ‘int test(int)’|



来源:https://stackoverflow.com/questions/31373689/constexpr-variable-evaluation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!