1. 程式人生 > >c++ 11 constexpr 常量表達式 簡單理解

c++ 11 constexpr 常量表達式 簡單理解

常量表達式(constexpr)

常量表達式機制是為了:

提供了更多的通用的值不發生變化的表示式

允許使用者自定義的型別成為常量表達式

提供了一種保證在編譯期完成初始化的方法(可以在編譯時期執行某些函式呼叫)

 

基本語法:

 

1.修飾常量表達式

    int var1 = 100;

    const int const_var2 = 200;

    const int const_var3 = var1;

    constexpr int constexpr_var1 = 3 + const_var2 * 4; //成立

   // constexpr int constexpr_var2 = 3 + var1 * 4; //錯誤

   // constexpr int constexpr_var3 = 3 + const_var3 * 4; //錯誤

 

2.修飾函式

constexpr int Inc(int i) {

    return i + 1;

}

   

constexpr int a = Inc(1); // 正確

constexpr int b = Inc(cin.get()); // 錯誤

constexpr int c = a * 2 + 1; // 正確,但是如果沒有Inc(1),也是錯誤的。

 

constexpr修飾的值要有初始值,和const不同的是初始化的值可以一個表示式,但是這個表示式的值必須是在編譯期間就能確定值的。

 

3.修飾類或者結構體

 

struct A {

    constexpr A(int xx, int yy): x(xx), y(yy) {}

    int x, y;

};

   

constexpr A aa(1, 2);

constexpr int ccc = aa.x;

enum {SIZE_X = aa.x, SIZE_Y = aa.y};//llvm報錯

Reference to local variable 'aa' declared in enclosing function 'main'

如果把constexpr A aa(1, 2);寫成全域性的就Ok,但是某些編譯器並不會報錯,我個人認為這個llvm編譯器不太合理的地方,如果緊緊是aa是一個區域性變數就不允許,但是aa本身的值是在編譯的時候就確認了的。

 

個人的理解就是constexpr擴充套件了常量的含義,從語法上支援更多的常量定義,對比巨集又有更好的型別檢測和安全性,更強的約束語法帶來更好的程式碼優化。

 

無意中在csdn論壇上看見大神的一段短話,摘錄下來,很值的體會

 

constexpr:不光是可以取代模板是某些常量的表達更簡潔,其實一個決定性的作用是支援地址類常量。這恰好補上了模板缺失的部分。比如有一個字串常量"abc",很自然的可以認為其中的元素也是常量地址,對一個有編譯期內容的常量地址取值理論上可以在編譯器確定結果,但實際上按舊語法卻不能直接拿去做為常量使用而是當作變數。

union帶建構函式、支援帶使用者定義建構函式的類作為其成員,本意是用來支援某種多型變數,比如根據某個標誌決定一個這樣的union當前是什麼型別。濫用則會導致資料錯誤。

noexcept支援推導,而容器元素在支援右值引用的情況下這類推導是很重要的。右值引用可以減少深拷貝的需求,但是在某些情況下會破壞強異常安全保證。利用noexcept推導來決定一個複雜型別作為容器元素的時候到底適合用移動還是適合用普通的拷貝策略來保證強異常安全。比如一個型別如果不支援無異常的移動(自身或任一基類或者資料成員的移動建構函式不支援noexcept,因此需要用到推導),則這個型別不適合移動而只能使用拷貝實現異常安全

轉自:https://www.cnblogs.com/budaixi/p/3857625.html