2015-07-12 62 views
3

這裏是我的代碼,我需要澄清發生的事情:Constexpr可變評價

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


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

constexpr的允許編譯時間計算,並根據我上面的代碼,因爲funct被聲明爲constexpr,允許如果參數是常量或constexpr本身,則進行編譯時計算。

我感到困惑的部分在於此部分,int x。由於它沒有被聲明爲constexpr,這是否意味着int x會在運行時獲得該值?這是否意味着聲明它爲constexpr int x意味着int x將在編譯時得到該值,而不像int x

+1

它會產生什麼不同?或者,你將如何能夠分辨這種差異? 'x'是一個局部變量,它*具有*在運行時被初始化。 –

+1

假設沒有優化,是在運行時評估聲明。但是,編譯器可以將這個程序優化爲無,因爲它什麼都不做。 –

+0

啊,我明白了。所以如果它是'int x'那麼它肯定會在運行時並且'constexpr'將會在編譯時? –

回答

4

這取決於許多問題上的編譯器。什麼樣的優化可能發生,等等。但是,constexpr本身並不支持編譯時計算。

把這個代碼:

#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)); 
} 

在我的x86_64的Gentoo系統,實際上仍然使這兩點打電話給所謂編譯時「測試」 GCC 4.8.4。我用系是

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

所以上面的代碼中,產生以下的機器代碼:

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

凡 「測試」 的ASM塊是:

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 

所以,就像你在這種情況下看到的那樣,它似乎對GCC如何生成該代碼幾乎沒有影響。即使你這樣做,你仍然會得到運行時算了一筆賬:

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

如果產生這種(測試地址稍微由於多加入一些代碼更改):

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 <[email protected]> 

它,然而,產生預期的結果,如果你聲明價值本身爲constexpr:

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

和相關的代碼爲:

0x400623 mov esi,0x37 
0x400628 mov edi,0x400714 
0x40062d mov eax,0x0 
0x400632 call 0x4004f0 <[email protected]> 

所以,從本質上講,如果僅僅用constexpr預先聲明方法聲明,則不保證編譯時計算。您還需要將您的變量聲明爲constexpr並分配給它。做這樣的聲明實際上要求編譯器靜態評估結果。如果你嘗試這樣做,並且「測試」未聲明爲constexpr,GCC會對你大喊:

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

+0

我明白了,謝謝你的詳細解釋。我會研究它。 –

+0

不客氣。 – Ragora

+0

只是一個後續問題,如果我構造一個constexpr構造函數,他們會自動constexpr? –