C++11新特性:constexpr變量和constexpr函數


C++11新特性:constexpr變量和constexpr函數

​ 本章將介紹constexpr變量和constexpr函數兩個知識點。在了解constexpr函數之前,首先要對常量表達式constexpr變量字面值類型字面值常量的定義有一個清晰的了解。

先驗知識

1.常量表達式

​ 指值不會改變並且在編譯過程中就能夠得到計算結果的值

const int max_files = 20;            //max_files是常量表達式
const int limit = max_files + 1;     //limit是常量表達式
int staff_size = 27;                 //staff_size不是常量表達式,因為它的數據類型不是const 
const int sz = get_size();           
//sz不是常量表達式,因為get_size()只有到運行的時候才知道結果,除非它是constexpr修飾的(C++ 11標准)

2.constexpr變量

​ C++11新標准規定,允許將變量聲明為constexpr類型以便由編譯器驗證變量的值是否是一個常量表達式。如果不是,編譯器報錯。同時,聲明為constexpr的變量一定是常量,而且必須用常量表達式初始化。

constexpr int mf = 20;              //正確,20是常量表達式
constexpr int limit = mf + 1;       //正確,mf + 1是常量表達式
constexpr int sz = size();         //未知,若size()函數是一個constexpr函數時即正確,反之錯誤。

int i = 10;
constexpr int t = i;                //錯誤,i不是常量

3.字面值類型

聲明constexpr變量時用到的類型被稱為字面值類型。算術類型、引用、指針、枚舉和一些特殊的類都屬於字面值類型,而IO庫、string類型則不屬於字面值類型,也就不能被定義為constexpr。

4.字面值常量

常量是指用const聲明或定義一個變量,使之成為常量。如const int bufSize = 512; #bufSize在程序中將不允許被修改,是常量。而字面值常量是指只能用它的值來稱呼的,不能被修改的值,如4、3.1415926、0x24、"BEIJING"

5.指針與constexpr

​ 對於指針而言,constexpr僅對指針本身有效與指針所指對象無關

const int *p = nullptr;            //正確,p是一個指向整型常量的指針
constexpr int *q = nullptr;        //正確,但q是一個指向  整數  的  常量指針

​ constexpr指針既可以指向常量也可以指向一個非常量

constexpr int *np = nullptr;         //正確,np是一個指向整數的常量指針,其值為空

int j = 0;
constexpr int i = 42;
//i和j都必須定義在函數體之外,否則constexpr指針無法指向。
constexpr const int *p = &i;                    /*p是常量指針,指向  整型常量i*/
constexpr int *p1 = &j;                       //p1是常量指針,指向  整數j(非常量)

constexpr函數

​ 指能用於常量表達式的函數。該函數要遵循規定:函數的返回類型及所有形參的類型都得是字面值類型(聲明constexpr變量時用到的類型),並且函數體中必須有且只有一條return語句

constexpr int new_sz() { return 42; }//constexpr函數
constexpr int foo = new_sz();
//在對變量foo初始化時,編譯器把對constexpr函數的調用替換成其結果值。為了能在編譯過程中隨時展開,constexpr函數被隱式地指定為內聯函數。

​ constexpr函數體內也可以包含其他語句,只要這些語句在運行時不執行任何操作即可。如空語句、類型別名、using聲明。

需要注意的是,我們允許constexpr函數的返回值並非一個常量???

​ 這里需要弄清楚字面值類型的意義。。。

//如果arg是常量表達式,則scale(arg)也是常量表達式
constexpr size_t scale(size_t cnt){ return new_sz() * cnt; }

//當scale的實參是常量表達式時,它的表達式也是常量表達式,反之則不然
int arr[scale(2)];	//正確:scale(2)是常量表達式
int i = 2;			//i不是常量表達式
int a2[scale(i)];	//錯誤:scale(i)不是常量表達式

注意,我們要把內聯函數和constexpr函數定義在頭文件中


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM