问题
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