const關鍵字
const修飾的對象一旦創建后其值就不能再改變,所以const修飾的對象必須初始化
用法:
-
定義常量對象,被const修飾的對象不能被更改
const int i = 42; //正確,編譯時初始化 const int j = get_size(); //正確,編譯時初始化 const int l; //錯誤,l未經初始化
-
默認狀態下,const對象僅在文件內有效,要想在多個文件直接共享const對象,必須在變量的定義之前添加extern關鍵字
-
可以把引用綁定到const對象上,我們稱之為對常量的引用。對常量的引用不能修改所綁定的對象
const int ci = 1024; const int &r1 = ci; //正確,引用及其引用的對象都是常量 r1 = 2048; //錯誤,r1是對常量的引用,不能修改 int &r2 = ci; //錯誤,r2是非常量引用,不能指向一個常量對象
對const的引用可能引用一個並非const的對象
int i = 42; int &r1 = i; //引用r1綁定1 const int &r2 = i; //r2也綁定對象i,但是不允許通過r2改變i的值 r1 = 0; //正確 r2 = 0; //錯誤
-
和引用一樣,可以將指針指向常量或者非常量。同時指針也是對象,因此指針也可以被const修飾。常量指針必須初始化,並且之后它的值就不能再更改了,把*放在const之前表示指針是一個常量
const double pi = 3.14; //pi是一個常量 double *ptr = pi; //錯誤,普通指針不能指向常量 const double *cptr = π //正確,cptr可以指向一個double的常量 *cptr = 42; //錯誤,不能給*cptr賦值 int errNumb = 0; int *const curErr = &errNumb; //curErr將一直指向errNumb const double pi = 3.14159; const double *const pip = π //pip是一個指向常量對象的常量指針
-
我們用頂層cost表示任意的對象是常量,底層const則表示指針和引用復合類型的基本類型部分有關
int i = 0; int *const p1 = &i; //不能改變p1的值,頂層const const int ci = 42; //不能改變ci的值,頂層const const int *p2 = &ci; //可以改變p2的值,底層const const int *const p3 = p2; //即是頂層const又是底層const const int &r = ci; //對於引用的聲明都是底層const
constexpr關鍵字
constexpr是C++11新引入的關鍵字,用來表示常量表達式。常量表達式是指值不會改變,並且在編譯過程中就能得到計算結果的表達式。constexpr限定在了編譯期就要初始化,const是可以再運行時初始化的。
int foo()
{
return 5;
}
int main()
{
const int p1 = foo(); //正確
constexpr int p2 = foo(); //錯誤,表達式必須含有常量值,無法調用非 constexpr 函數
}
constexpr只能定義字面值類型,如算術類型,指針和引用。而類似IO庫,string類型則不屬於字面值類型,也就不能被定義為constexpr。
盡管指針和引用可以被定義為constexpr,但是他們的初始值必須為nullptr或者0,或者是存儲於某個固定地址中的對象。
auto和decltype關鍵字
auto和decltype關鍵字都可以進行類型推導,可以在編譯期就推導出變量或者表達式所屬的類型。
-
auto類型說明符:讓編譯器在編譯期通過初始值推算變量的類型。在一條語句聲明多個變量時,基礎數據類型必須一樣
auto i = 0, *p = &i; //正確,i為整型,p為整型指針 auto sz = 0, pi = 3.14; //錯誤,sz為整型,pi為雙精度浮點數
在不聲明的情況下,編譯器會以引用對象的類型作為auto的類型。
auto也會忽略頂層const,保留底層const
int i = 0, &r = i; auto a = r; //a是int const int ci = i, &cr = ci; auto b = ci; //b是int auto c = cr; //c是int auto d = &i; //d是int* auto e = &ci; //e是一個const int*
-
decltype類型說明符:用於編譯器推導表達式類型,表達式並不會進行實際上的運算
decltype(exp) i; //exp可以是表達式,也可以是函數調用,這時候i是表達式的類型或者函數調用的返回值 //其他情況,若exp為左值,decltype(exp)是exp類型的左值引用
與auto不同,對於頂層const的處理不相同
const int ci = 0, &cj = ci; auto x = ci; //x是int decltype(ci) y = ci; //y是const int auto z = cj; //z是int auto az = &cj; //az是const int* decltype(cj) cz = cj; //cz是const int&
當exp是加了括號的變量,結果將是引用
int i = 42; decltype((i)) d; //錯誤,d是int&,必須初始化 decltype(i) e; //正確,e是未初始化的int