运行时常量池在哪里_C++干货系列——从编译期常量谈到constexpr(一)
C++20都支持虛函數的constexpr了,我打算用三篇讀文章講清楚編譯期常量和constexpr這個東西和編譯期常量的關系,即為什么需要他來輔助解決這個問題。最后幫助讀者在實際編碼過程中能夠有意識地去運用他們,這才是終極目標。這篇文章中會講到隱藏在日常編程中的各種編譯期常量,以及他們存在的意義。
從編譯期常量談起
想要用編譯期常量就要首先知道它們是什么,一般出現在哪里和運行期常量有什么區別,因此我打算用第一篇文章重點分析編譯期常量以及使用他們有什么好處。
編譯期常量(Compile-time constants)是C++中相當重要的一部分,整體而言他們有助提高程序的正確性,并提高程序的性能。這篇文章中出現的編譯期常量都是在C++11之前就可以使用的,constexpr是C++11的新特性,所以各位不要有心理包袱。
總有些東西是編譯器要求編譯期間就要確定的,除了變量的類型外,最頻繁出現的地方就是數組、switch的case標簽和模板了。
數組中的編譯期常量
如果我們想要創建一個不是動態分配內存的數組,那么我們就必須給他設定一個size——這個size必須在編譯期間就知道,因此靜態數組的大小是編譯期常量。
int只有這么做,編譯器才能準確地解算出到底要分配給這個數組多少內存。如果這個數組在函數中,數組的內存就會被預留在該函數的棧幀中;如果這個數組是類的一個成員,那么編譯器要確定數組的大小以確定這個類成員的大小——無論哪種情況,編譯器都要知道這個數組具體的size。
有些時候我們不用顯示得指明數組的大小,我們用字符串或花括號來初始化數組的時候,編譯器會實現幫我們數好這個數組的大小。
int模板中的編譯期常量
除了類型以外,數字也可以作為模板的參數。這些數值變量包括int,long,short,bool,char和弱枚舉enum等。
enumCase labels
既然編譯器在初始化模板的時候必須知道模板的類型,那么這些模板的參數也必須是編譯期常量。
switch語句的分支判斷也必須是編譯期常量,和上邊模板的情況非常類似。
void使用編譯期常量有什么好處
如果編譯期常量的使用方法只有上邊呈現的幾種,那你大概會感覺有些無聊了。事實上,關于編譯期常量我們能做的事情還有許多,他們能幫助我們去實現更高效的程序。
更安全的程序
編譯期常量能讓我們寫出更有邏輯的代碼——在編譯期就體現出邏輯。比如矩陣相乘:
class我們都知道,兩個矩陣相乘,當且僅當左矩陣的列數等于右矩陣的行數,如果不滿足這個規則的話,那就完蛋了,所以針對上邊矩陣的乘法,我們在函數中要做一些判斷:
Matrix但是如果我們在編譯期就知道了矩陣的size,那么我們就可以把上邊的判斷放在模板中完成——這樣的話不同size的矩陣一下子就成了不同類型的變量了。這樣我們的矩陣乘法也相應變得簡單了一些:
template在這個例子中,編譯器本身就阻止了錯誤的發生,還有很多其他的例子——更復雜的例子在編譯期間使用模板。從C++11后有一堆這樣的模板都定義在了標準庫STL中,這個之后再說。所以大家不要覺得上邊這種做法是脫褲子放屁,相當于我們把運行時的條件判斷交給了編譯期來做,前提就是矩陣的類型必須是編譯期常量。你可能會問,除了像上邊直接用常數來實例化矩陣,有沒有其他方法來告訴編譯器這是個編譯期常量呢?請往下看。
編譯優化
編譯器能根據編譯期常量來實現各種不同的優化。比如,如果在一個if判斷語句中,其中一個條件是編譯期常量,編譯器知道在這個判斷句中一定會走某一條路,那么編譯器就會把這個if語句優化掉,留下只會走的那一條路。
if在上例中,編譯器就會直接利用其中某一個cout語句來替換掉整個if代碼塊——反正運行代碼的機器是32還是64位的又不會變。 另一個可以優化的地方在空間優化。總體來說,如果我們的對象利用編譯期常數來存儲數值,那么我們就不用在這個對象中再占用內存存儲這些數。就拿本文之前的例子來舉例:
- someStruct結構中包含一個‘unsigned long’,一個‘char’,和一個‘color’,盡管如此他的實例對象卻只占用一個byte左右的空間。
- 矩陣相乘的時候,我們在矩陣中也沒必要花費空間去存儲矩陣的行數和列數了。
結語
這一篇文章只講到了編譯期常量,為了使編譯器在編譯期間計算出常量,我們在C++11標準之前和之后都采用了不同的方法去實現它。在第二篇文章中,我會將主要精力放在C++11標準之前的編譯期計算的問題,通過展現一系列蹩腳的方法來引出我們的主角——constexpr。
該系列的第二篇已經出來啦!點贊收藏后走這里哈:
小天狼星不來客:C++干貨系列——從編譯期常量談到constexpr(二)?zhuanlan.zhihu.com這篇文章收錄在我的專欄中哦:
C++干貨系列?zhuanlan.zhihu.com點個關注,及時獲得最新干貨。
總結
以上是生活随笔為你收集整理的运行时常量池在哪里_C++干货系列——从编译期常量谈到constexpr(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在将varchar值id转换为int时失
- 下一篇: python给函数设置超时时间_在 Li