C 11之常量表示式

2021-07-23 17:29:10 字數 2938 閱讀 8125

2013-09-17

c++11有一些這樣的改善,這種改善保證寫出的**比以往任何時候的執行效率都要好。這種改善之一就是生成常量表示式,允許程式利用編譯時的計算能力。假如你熟悉模板元程式設計,你將發現constexpr使這一切變得更加簡單。假如你不知道模板元程式設計,也沒什麼。constexpr使我們很容易利用上編譯時程式設計的優勢。

常量表示式主要是允許一些計算發生在編譯時,即發生在**編譯而不是執行的時候。這是很大的優化:假如有些事情可以在編譯時做,它將只做一次,而不是每次程式執行時。需要計算乙個編譯時已知的常量,比如特定值的sine或cosin?確實你亦可以使用庫函式sin或cos,但那樣你必須花費執行時的開銷。使用constexpr,你可以建立乙個編譯時的函式,它將為你計算出你需要的數值。使用者的電腦將不需要做這些工作。

為了使函式獲取編譯時計算的能力,你必須指定constexpr關鍵字到這個函式。

constexpr

intmultiply

(intx,

inty

)// 將在編譯時計算

const

intval

=multiply(10

,10);

除了編譯時計算的效能優化,constexpr的另外乙個優勢是,它允許函式被應用在以前呼叫巨集的所有場合。例如,你想要乙個計算陣列size的函式,size是10的倍數。如果不用constexpr,你需要建立乙個巨集或者使用模板,因為你不能用函式的返回值去宣告陣列的大小。但是用constexpr,你就可以呼叫乙個constexpr函式去宣告乙個陣列。

constexpr

intgetdefaultarraysize

(int

multiplier

)int

my_array

[getdefaultarraysize(3

)];

乙個constexpr有一些必須遵循的嚴格要求:

注意遞迴並不受限制。但只允許乙個返回語句,那如何實現遞迴呢?可以使用三元運算子(?:)。例如,計算n的階乘:

constexpr

intfactorial

(intn)

現在你可以使用factorial(2),編譯器將在編譯時計算這個值,這種方式執行更巧妙的計算,與內聯截然不同。你無法內聯乙個遞迴函式。

constexpr函式還有那些特點?

乙個constexpr函式,只允許包含一行可執行**。但允許包含typedefs、 using declaration && directives、靜態斷言等。

乙個宣告為constexpr的函式同樣可以在執行時被呼叫,當這個函式的引數是非常量的:

intn;

cin>>n;

factorial(n

);

這意味著你不需要分別寫執行時和編譯時的函式。

假如你有乙個circle類:

class

circle

double

getarea

()const

private:

int_x

;int_y;

int_radius;};

你希望在編譯期構造乙個circle接著算出他的面積。

constexpr

circlec(

0,0,

10);

constexpr

double

area=c

.getarea

();

事實證明你可以給circle類做一些小的修改以完成這件事。首先,我們需要將建構函式宣告為constexpr,接著我們需要將getarea函式宣告為constexpr。將建構函式宣告為constexpr則執行建構函式在編譯期執行,只要這個建構函式的引數為常量,且建構函式僅僅包含成員變數的constexpr構造(所以預設構造可以看成constexpr,只要成員變數都有constexpr構造)。

class

circle

constexpr

double

getarea

()private:

int_x

;int_y;

int_radius;};

假如你將乙個成員函式標記為constexpr,則順帶也將它標記為了const。如果你將乙個變數標記為constexpr,則同樣它是const的。但相反並不成立,乙個const的變數或函式,並不是constexpr的。

到這裡我們講到的constexpr功能都可以通過模板元程式設計實現。但constexpr支援的一項能力是可以計算浮點型的資料。因為double和float不是有效的模板引數,你不可以輕易的通過模板編譯期計算浮點數的值。而constexpr允許編譯期計算浮點型資料。

c++開發者早就深受修改乙個標頭檔案則引發重新編譯導致編譯緩慢的困擾。而constexpr可能引入增加編譯時間的風險,但也有一些技術去降低這種風險。首先,因為constexpr函式相同的引數會輸出相同的結果,所以它們可以被memoized,事實上gcc已經支援memoization。

因為可以對constexpr函式memoize,所以用constexpr函式替換模板函式的地方,(編譯)效能不會變得更壞,但**會變得清晰。事實上,替換掉一部分模板例項,編譯會顯著加快。

最後,標準允許編譯器去限制遞迴函式的級數。這樣可以限制深度遞迴的編譯效能損耗。

constexpr需要編譯器支援編譯期的遞迴,所以也不奇怪支援constexpr的編譯器並不多,就我所知只有g++4.7支援這一特性。[注:到我翻譯時,intelc++13、clang3.1也都支援了,不過vs2013還是不支援]

ps:常量表示式解決了陣列無法使用函式返回值定義大小的問題。

c 11 常量表示式

define crt secure no warnings include include include include 常量表示式主要是允許一些計算發生在編譯時,即發生在 編譯而不是執行的時候。這是很大的優化 假如有些事情可以在編譯時做,它將只做一次,而不是每次程式執行時都計算。constexp...

c 11 常量表示式

define crt secure no warnings include include include include 常量表示式主要是允許一些計算發生在編譯時,即發生在 編譯而不是執行的時候。這是很大的優化 假如有些事情可以在編譯時做,它將只做一次,而不是每次程式執行時都計算。constexp...

C 11系列 常量表示式

c 11有一些這樣的改善,這種改善保證寫出的 比以往任何時候的執行效率都要好。這種改善之一就是生成常量表示式,允許程式利用編譯時的計算能力。假如你熟悉模板元程式設計,你將發現constexpr使這一切變得更加簡單。假如你不知道模板元程式設計,也沒什麼。constexpr使我們很容易利用上編譯時程式設...