C++ constexpr的使用小結(jié)
constexpr是C++的修飾詞,用于指定“編譯期可以求數(shù)值的常量表達(dá)式”,可用于修飾變量,函數(shù),類/結(jié)構(gòu)體,構(gòu)造函數(shù)/析構(gòu)函數(shù),模板五種情況,作用就是支持編譯期常量處理。constexpr的實(shí)際應(yīng)用中最常用的是修飾變量和函數(shù)。
constexpr用于修飾變量,可以構(gòu)建真常量,即編譯器常量。constexpr用于修飾函數(shù),可以用于編譯期求值;constexpr用于修飾類/結(jié)構(gòu)體??梢杂脕碓诰幾g期構(gòu)造對象;constexpr用于修飾構(gòu)造函數(shù)/析構(gòu)函數(shù),可以在編譯器就對類對象進(jìn)行初始化/銷毀;constexpr用于修飾模板,在編譯期間完成模板實(shí)例化進(jìn)行求數(shù)值。
增加編譯期間求解的效果是提升性能、增強(qiáng)類型安全。
實(shí)例1——constexpr修飾變量:
#include <iostream> constexpr int MAXsize = 100; // 由constexptr修飾的int型真常量, //在編譯期就可以通過直接賦值確定取值為100. constexpr int OVERsize = MAXsize + 50; //在編譯期可以通過計(jì)算得到確定取值為150. //由constexpr修飾的MAXsize和OVERsize兩個真常量,分別取值100和150. //編譯正常。符合處理直覺。
提問: constexpr 可以修飾變量,此時該變量是編譯期常量(值必須在編譯期確定,且生命周期內(nèi)不可修改,比 const 更嚴(yán)格)如果這個變量的取值在編譯期間沒有確定會報(bào)錯嗎?還是任意給這個變量取定一個隨機(jī)值?取定隨機(jī)值會導(dǎo)致這個變量實(shí)際沒有可用效果? 以及這里講的生命周期不可修改是什么意思?一個constexpr修飾的真常量的生命周期不就是整個程序運(yùn)行的期間都有效嗎?編譯期常量即真常量是不占用C++堆內(nèi)存和棧內(nèi)存的吧!
解答:
// constexpr 修飾變量,這個變量的數(shù)值必須在編譯期確定,生命周期內(nèi)不可修改。
// 如果編譯期間這個變量的數(shù)值沒有確定指定,會直接編譯報(bào)錯,無隨機(jī)值。
// constexpr 修飾得到的真常量在生命周期內(nèi)都只具有只讀屬性,不可修改。
// constexpr 修飾得到的真常量的生命周期取決于變量定義所在的作用域決定。
// 即constexpr只負(fù)責(zé)跟編譯器通力合作在編譯期間確定數(shù)值。
// 至于這個真常量在何時失效取決于這個變量的自身的作用域,
// 即定義在函數(shù)內(nèi)部的變量,即便加上constexpr修飾,
// 這個真常量的生命周期依然只在函數(shù)內(nèi)的局部作用域效果下。constexpr修飾的真常量被存儲在靜態(tài)只讀數(shù)據(jù)區(qū)。
總結(jié)1:
constexpr修飾變量,得到真常量,存儲在靜態(tài)存儲區(qū),不占用運(yùn)行內(nèi)存;(因此增強(qiáng)性能)constexpr修飾得到的真常量,如果沒有在編譯期指定,直接報(bào)錯。constexpr修飾得到的真常量,生命周期內(nèi)權(quán)限為只讀,不可修改。constexpr修飾得到的真常量,生命周期長度取決于變量本身的生命周期。
實(shí)例2——constexpr修飾函數(shù):
表示這個函數(shù),如果入?yún)⑹蔷幾g期常量,在編譯期完成計(jì)算得到處理結(jié)果。如果入?yún)⒉皇蔷幾g期間常量,那就退化成普通函數(shù)。兩種情況都不會報(bào)錯。UDL和普通函數(shù)都支持這種退化兼容。
//constexpr修飾UDL(自定義字面值運(yùn)算符)
constexpr long long operator "" _KM2m(long long kilometer) {
return kilometer*1000;
}
//constexpr修飾普通函數(shù)
constexpr int add(int a, int b){
return a + b;
}
實(shí)例3——constexpr修飾類/結(jié)構(gòu)體:
作用是在編譯期構(gòu)造類對象,即編譯期常量對象。 要求:
- 類的構(gòu)造函數(shù)必須是
constexpr構(gòu)造函數(shù); - 編譯期內(nèi)需調(diào)用的成員函數(shù)也必須有
constexpr修飾; - 類的成員變量中,對于被
constexpr使用/依賴的靜態(tài)成員變量,必須在類內(nèi)constexpr修飾。而且最好直接用static constexpr
//constexpr修飾結(jié)構(gòu)體(在C++中將結(jié)構(gòu)體視為類的一種)
struct Point{
//constexpr 修飾構(gòu)造函數(shù)
constexpr Point(int x_, int y_) : x(x_), y(y_) {}
// C++中約定俗成用 變量名右加下劃線 表示類成員變量的命名。
// x(x_), y(y_) 是 C++ 中的「成員初始化列表(Member Initialization List)
// 效果是將x_,y_的值對應(yīng)賦值給x,y
// `x(x_)` 和 `x=x_` 在初始化列表中等價
//constexpr 修飾構(gòu)造函數(shù)
constexpr int get_x() const {
return}
}
int x;
int y;
}
int main () {
//編譯器構(gòu)造Ponit對象
constexpr Point p0(10,20);
//編譯期調(diào)用成員函數(shù),獲取數(shù)值
constexpr int x_val = p0.get_x();
return 0;
}
- 非靜態(tài)成員變量是指屬于單個對象的變量,每個對象獨(dú)一份,生命周期隨對象變化;
- 靜態(tài)成員變量屬于類本身的,所有對象共享一份,生命周期貫穿程序。
- 靜態(tài)const成員變量:類內(nèi)直接初始化,因?yàn)樨灤┏绦虻纳芷?,且在運(yùn)行期間數(shù)值不可修改,是綁定在整個類上的變量。
static const變量類型 變量名 = 初始化數(shù)值;static constexpr變量類型 變量名 = 初始化數(shù)值; 效果更好。
- -這里的static其實(shí)是指類共享。靜態(tài)變量本質(zhì)是類共享變量;非靜態(tài)變量是類不共享變量。
- 靜態(tài)const成員變量:類內(nèi)直接初始化,因?yàn)樨灤┏绦虻纳芷?,且在運(yùn)行期間數(shù)值不可修改,是綁定在整個類上的變量。
實(shí)例4——constexpr修飾構(gòu)造函數(shù)/析構(gòu)函數(shù):
構(gòu)造函數(shù)用constexpr修飾,要么非空要么只涉及基本四則運(yùn)算和判斷的簡潔函數(shù)體。 析構(gòu)函數(shù)用constexpr修飾,得到的效果是編譯期對象銷毀時沒有運(yùn)行期開銷。 (constexpr修飾的效果要么是用于設(shè)定真常量,要么是能在編譯期間能處理的事情給處理了。)
class MyInt{
public:
//構(gòu)造函數(shù)
constexpr MyInt (int val_) : val(val_) {}
//析構(gòu)函數(shù)
constexpr ~MyInt() = default; //析構(gòu)函數(shù)直接 = default 就行。
//成員函數(shù)
constexpr int get_val() const {
return val;
}
private:
int val;
};
int main() {
//在編譯期構(gòu)造 MyInt 對象
constexpr MyInt mi(100);
constexpr int val = mi.get_val(); // 編譯期求值為100
return 0;
}
關(guān)聯(lián)說明類成員函數(shù)的const尾綴修飾: constexpr int get_val() const { return val; //這個const成員函數(shù)只讀取,沒有修改val的權(quán)限。 }
const成員函數(shù)
作用是限定這個成員函數(shù)對成員變量的操作權(quán)限僅僅是只讀。
- 禁止修改類的非靜態(tài)成員變量,確保這個函數(shù)只進(jìn)行只讀操作,不會改變對象的狀態(tài)。
- 禁止調(diào)用非
const成員函數(shù)。
const是 “承諾不修改成員變量”,僅支持運(yùn)行期執(zhí)行;constexpr是 “支持編譯期求值”,
實(shí)例5——constexpr修飾模板template:
使模板實(shí)例化后具備編譯器求值能力。
template <template T>
constexpr T max_val(T a, T b){
return a > b ? a : b;
}
int main() {
constexpr int max_num = max_val(5,10);
//編譯期求值: max_val(5,10)實(shí)例化得到int型數(shù)據(jù),取值為10.
return 0;
}
到此這篇關(guān)于C++ constexpr的使用小結(jié)的文章就介紹到這了,更多相關(guān)C++ constexpr內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于C語言實(shí)現(xiàn)點(diǎn)菜系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了基于C語言實(shí)現(xiàn)點(diǎn)菜系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-11-11
c++動態(tài)庫調(diào)用的實(shí)現(xiàn)
本文主要介紹了c++動態(tài)庫調(diào)用的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07
C++實(shí)現(xiàn)循環(huán)隊(duì)列和鏈?zhǔn)疥?duì)列的示例
下面小編就為大家分享一篇C++實(shí)現(xiàn)循環(huán)隊(duì)列和鏈?zhǔn)疥?duì)列的示例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-12-12
C語言實(shí)現(xiàn)隨機(jī)生成6位數(shù)密碼
這篇文章主要為大家詳細(xì)介紹了如何使用C語言實(shí)現(xiàn)一個簡單而實(shí)用的隨機(jī)密碼生成器,該生成器將生成包含字母、數(shù)字和特殊字符的隨機(jī)密碼,有需要的小伙伴可以參考下2023-11-11
詳解如何在code block創(chuàng)建一個C語言的項(xiàng)目
這篇文章主要介紹了詳解如何在code block創(chuàng)建一個C語言的項(xiàng)目,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12

