|
constexpr用于在C++11中申報常量表達式(constexpression),可用于函數返回值、函數參數、數據申報和類結構函數。 
常量表達式指數不會改變,在編譯期間得到計算結果,例如: const int i=3; //i是一個常變量
const int j=i+1; //j是一個常變量,i+1是一個常量表達式
int k=23; //k的值可以改變,從而不是一個常變量
const int m=f(); //m不是常變量,m的值只有在運行時才會獲取1234復制代碼類型:[cpp] 1、constexpr的應用。 1)常量表達函數。 若能在編譯過程中確定函數返回值,則可使用constexpr修改函數返回值,使函數成為常量表達式函數。 constexpr int f(){return 1;}1復制代碼類型:[cpp] 請注意,constexpr修改函數的返回值需要滿足以下條件: (a)函數必須有返回值; (b)函數體只有單一的return語句; (c)return語句中的表達式也必須是常量表達式; 使用前必須對函數進行定義。 2)常量表達式值。 一般而言,如果確定變量為常量表達式,則聲明為constexpr類型。 constexpr int i=3; //i是一個常變量constexpr int j=i+1; //i+1是一個常變量constexpr int k=f(); //只有f()是一個constexpr函數時,k才是一個常量表達式123復制代碼類型:[cpp] 必須明確的是,在constexpr聲明中,如果定義了指針,constexpr只對指針有效,與指針所指的對象無關。 const int *p=nullptr; //p是一個指向整型常量的指針(pointer to const)constexpr int *p1=nullptr; //p1是一個常量指針(const pointer)12復制代碼類型:[cpp] 若自定義類型對象為常量表達式,則在定義自定義類型時,需要將constexpr作用于自定義類型的構造函數。 struct MyType {
int i; constexpr MyType(int x):i(x){}
}; constexpr MyType myType(1);12345復制代碼類型:[cpp] 作用于自定義類型的constexpr結構函數需要滿足以下條件: (a)構造函數體必須為空; (b)初始化列表只能使用常量表達式。 3)其他常量表達式應用。 (a)常量表達式作用于函數模板。 常量表達式可以作用于函數模板,但由于函數模板參數的不確定性,實例化模板函數可能不符合常量表達式的條件。此時,C++11標準自動忽略constexpr。 struct NotConstType {
int i;
NotConstType(int x) :i(x) {}
};
NotConstType myType; //constexpr作用于函數模板
template <typename T> constexpr T ConstExpFunc(T t) { return t;
} int main(){
NotConstType objTmp = ConstExpFunc(myType); //編譯通過,ConstExpFunc實例化為普通函數,constexpr被忽略
constexpr NotConstType objTmp1 = ConstExpFunc(myType); //編譯**失敗**
constexpr int a = ConstExpFunc(1); //編譯通過,ConstExpFunc實例化為常量表達式函數
}12345678910111213141516復制代碼類型:[cpp] (b)constexpr元編程。 constexpr可以作用于遞歸函數,實現編譯時期的數值計算,即constexpr元編程。根據C++11標準,常量表達式應至少支持512層遞歸。 constexpr int Fibonacci(int n){ return (n == 1) ? 1 : (n == 2 ? 1 : Fibonacci(n - 1) + Fibonacci(n - 2));
} int main(){ constexpr int fib8 = Fibonacci(8); //編譯期常量等于21
}1234567復制代碼類型:[cpp] 請注意,constexpr元編程并非C++11標準強制編譯器必須實現,編譯器可以有選擇地實現。換句話說,編譯器可能不支持遞歸常量表達式函數。但也不用太擔心,主流C++編譯器都是支持的,比如GCC和VC++。 2、constexpr和const的區(qū)別。 const可以修改函數參數。函數返回值。函數本身。類const在不同的使用場景中有不同的含義,但在大多數情況下,const描述的是運行時常量性,即數據在運行過程中是不可改變的。 constexpr可以修改函數參數、函數返回值、變量、類結構函數、函數模板等。,這是一種比const更嚴格的約束。它修改的表達式不僅具有運行時常量,還具有編譯時常量,即constexpr修改的表達式值可以在編譯過程中知道。我們來看看實際應用的區(qū)別: const int getConst(){ return 1; } enum{ e1=getConst(),e2}; //編譯出錯
//換成constexpr即可在編譯期確定函數返回值用于初始化enum常量
constexpr int getConst(){ return 1; } enum{ e1=getConst(),e2}; //編譯OK123456復制代碼類型:[cpp] 在constexpr出現之前,可以在編譯期初始化的const表達式是隱含的常量表達式(implicitconstexpr),直到c++11、constexpr才從const中細分為關鍵詞。 const自1983年C++剛改名以來就存在。面對constexpr,我們應該盡可能合理地使用constexpr來幫助編譯器優(yōu)化代碼。
|