C 11的constexpr關鍵字

2021-10-22 23:58:33 字數 2833 閱讀 4984

c++11有一些這樣的改善,

這種改善保證寫出的**

比以往任何時候的執行效率都要好。

這種改善之一: 假如

你熟悉模板元程式設計

你將發現constexpr使這一切變得更加簡單。

假如你不知道模板元程式設計

也沒什麼。

constexpr使我們很容易利用上編譯時程式設計的優勢。

常量表示式主要是允許一些計算發生在編譯時,即發生在**編譯而不是執行的時候。

這是很大的優化:假如有些事情可以在編譯時做,它將只做一次,而不是每次程式執行時。

需要計算乙個編譯時已知的常量,比如特定值的sine或cosin?確實你亦可以使用庫函式sin或cos,但那樣你必須花費執行時的開銷。使用constexpr,你可以建立乙個編譯時的函式,它將為你計算出你需要的數值。使用者的電腦將不需要做這些工作。

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

constexpr int multiply (int x, int y)

// 將在編譯時計算

const int val = multiply( 10, 10 );

除了編譯時計算的效能優化,constexpr的另外乙個優勢是,它允許函式被應用在以前呼叫巨集的所有場合。

例如,你想要乙個計算陣列size的函式,size是10的倍數。

如果不用constexpr,你需要建立乙個巨集或者使用模板,因為你不能用函式的返回值去宣告陣列的大小。

但是用constexpr,你就可以呼叫乙個constexpr函式去宣告乙個陣列。

constexpr int getdefaultarraysize (int multiplier)

int my_array[ getdefaultarraysize( 3 ) ];

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

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

constexpr int factorial (int n)

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

constexpr函式還有那些特點?

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

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

int n;

cin >> n;

factorial( n );

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

假如你有乙個circle類:

class circle

double getarea () const

private:

int _x;

int _y;

int _radius;

};

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

constexpr circle c( 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還是不支援]

分類: cpp

C 11新標準constexpr關鍵字

constexpr是c 11新標準規定的規定的關鍵字。有時我們很難分辨乙個初始值是不是常量表示式,當然可以定義乙個const變數並把它的初始值設為我們認為的某個常量表示式,但在實際使用時,儘管要求如此卻常常發現初始值並非常量 表示式的情況。可以說,這時的物件的定義與使用根本就是兩回事。c 11新標準...

C 11新標準之五 constexpr

常量表示式必須在編譯期間計算出它的值並且 它的值不可以被改變。在c 11中,我們可以通過宣告constexpr讓編譯器確定乙個變數是不是常量表示式,宣告為constexpr的變數是const型別的變數,它必須由常量表示式來初始化。例如 cpp view plain copy constexpr in...

C 11 constexpr 關鍵字用法

constexpr 是 c 11 中增加的關鍵字,我們可以使用該關鍵字定義以下物件 編譯期常量 常量表示式函式 編譯期常量物件。以下 執行環境為 win10 專業版 vs2019 社群版。常量分為編譯期常量 執行期常量。編譯期常量指的是在編譯階段就可以確定其值,並將其結果展開到使用的地方,不占用記憶...