C 11 constexpr 關鍵字用法

2021-10-12 17:52:12 字數 3504 閱讀 1661

constexpr 是 c++11 中增加的關鍵字,我們可以使用該關鍵字定義以下物件:

編譯期常量;

常量表示式函式;

編譯期常量物件。

以下**執行環境為:win10 專業版 + vs2019 社群版。

常量分為編譯期常量、執行期常量。

編譯期常量指的是在編譯階段就可以確定其值,並將其結果展開到使用的地方,不占用記憶體空間。

執行期常量本質上是唯讀的變數,需要占用記憶體空間,編譯時無法確定其值,執行時,無法修改其值。

constexpr 關鍵字就是用來定義編譯期的常量。

有些同學可能想,constexpr 和 const 有什麼區別呢?

constexpr 只能定義編譯期常量,而 const 可以定義編譯期常量,也可以定義執行期常量。

請看下面 const 的**:

void test()

第 3 行定義乙個編譯期常量。

第 6 行定義了乙個執行期常量。這是因為 b 是乙個變數,編譯期無法確定其值,必須到執行期才能確定。而 c 的值必須等到 b 確定才能確定,所以,c 是乙個執行期常量。

上面第 6 行**中的常量定義如果將 const 換成 constexpr ,則**就會報語法錯誤,因為 constexpr 只能定義編譯期常量。

void test()

上述**編譯報錯如下:

說到常量有些同學可能不太清楚,程式中為什麼要使用常量呢?有兩點原因如下:

程式中總是需要一些不能修改的資料,寫成變數則就有被意外修改的風險。

常量可以在編譯期確定其值,某些場景下可以將一些計算任務放在編譯階段,從而提公升程式效率。

什麼是常量表示式函式呢?請看下面的普通函式:

int my_sum(int n)

return n + my_sum(n - 1);

}

普通函式必須在執行時才能執行,進而計算出結果。而常量表示式函式要求函式在編譯期就計算出結果,執行時直接使用結果。也就是說將函式的執行從執行階段轉移到編譯階段,提公升程式執行效率。

將上面的 my_sum 函式定義為常量表示式函式非常簡單,只需要在函式返回值型別前面加上 constexpr 關鍵字即可。示例**如下:

constexpr int my_sum(int n)

return n + my_sum(n - 1);

}

為了能夠讓 my_sum 函式在編譯階段計算出結果,我們必須使用 constexpr 編譯期常量來儲存常量表示式函式的結果,否則 my_sum 函式仍然會在執行期執行。如下**所示:

constexpr int my_sum(int n)

return n + my_sum(n - 1);

}void test()

我們在 vs 2019 中檢視第 13 行**對生成的彙編**如下:

mov   dword ptr [a], 6
第 13 行**只對應一行彙編指令,數字 6 則是編譯階段執行 my_sum(3) 的計算結果。

如果將 constexpr 去掉,則第 13 行對應的彙編**如下:

push      3  

call my_sum (03913b1h)

add esp,4

mov dword ptr [a],eax

從彙編指令的條數來看,常量表示式函式明顯較少。並且,執行期的函式計算每次都需要呼叫 my_sum, 而常量表示式則不是,執行效率更高。

編譯期常量物件的任何計算都在編譯期完成。定義編譯期常量物件,有以下幾點要求:

建構函式使用 constexpr 修飾,必須使用初始化列表對成員進行初始化。

物件呼叫的成員函式必須使用 constexpr 修飾。請看下面的示例**:

class box

constexpr int get_volume() const

int get_sum() const

public:

int m_l;

int m_w;

int m_h;

};void test()

第 4 行 box 的建構函式使用 constexptr 修飾,並且使用初始化列表對成員進行初始化。這就保證了物件成員 m_l、m_w、m_h 在編譯期確定其值。

第 5 行 get_volume 函式也被定義為了常量表示式成員函式,呼叫該函式則會在編譯階段計算出結果。

第 10 行 get_sum 函式則是普通函式,該函式必須宣告為 const 函式,否則無法被常量物件呼叫。

第 23 行 box 型別的物件 box 必須使用 constexpr 來修飾,使得其能夠呼叫常量表示式建構函式。該行**對應的彙編**如下:

constexpr box box(10, 20, 30);

mov dword ptr [box], 0ah

mov dword ptr [ebp-10h], 14h

mov dword ptr [ebp-0ch], 1eh

其中 0ah 為十六進製制,對應十進位制為 10,14h 對應十進位制為 20, 1eh 對應十進位制為 30, 三行彙編**的作用就是將 10、20、30 賦值給成員變數 m_l、m_w、m_h。注意:此處並沒有呼叫 box 建構函式。

第 24 行通過常量物件 box 呼叫常量表示式成員函式,使得在編譯期計算出函式的執行結果,並賦值給編譯期常量 volume。該行**對應的彙編**如下:

constexpr int volume = box.get_volume();

mov dword ptr [volume], 1770h

其中, 十六進製制 1770h 對應的十進位制為 6000,該行**的作用是將值賦值 6000 給常量 volume。函式 get_volume 已經在編譯期執行完畢,執行期直接使用計算結果 6000。

第 25 行通過常量物件呼叫了普通函式 show,該函式會在執行期進行執行。該行**對應的彙編**如下:

int my_sum = box.get_sum();

lea ecx, [box]

call box::get_sum (0fd1131h)

mov dword ptr [my_sum],eax

call 指令表示呼叫後面的函式。我們可以看到,執行期呼叫了 get_sum 函式計算結果,而不是直接使用結果。

至此,關於 constexpt 講解完畢,希望對你有所幫助!

C 11的constexpr關鍵字

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

C 11新標準constexpr關鍵字

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

三 constexpr關鍵字(從C到C )

內容參考於 21天學通c 第八版 1.示例 include constexpr double getpi constexpr double twicepi intmain 執行結果 constant pi contains value 3.14286 constexpr getpi returns ...