摘要訊息 : 再次理解 C++ 11 引入的 constexpr
.
0. 前言
C++ 11 中引入的所有特性中, 最讓人困惑的也許是 constexpr
. 在《C++ 學習筆記》中, 我們詳細介紹過 constexpr
, 這篇文章旨在幫助閣下深入理解 constexpr
. 如果閣下一點都不了解 constexpr
, 可以先閱讀《C++ 學習筆記》.
本文在 2022 年 5 月 16 日进行一次更新和修正. 修正之后本文已经归档, 不再享受更新.
1. 細談 constexpr
針對變數標識的 constexpr
表示該變數必定是編碼期就已知的變數, 也就是所謂的字面值常數表達式; 而針對函式標識的 constexpr
表明該函式有編碼期處理的能力, 但是函式的運作不一定就非要在編碼期, 也可以在運作期. 這個總結透露出了一個重要的信息, 就是 constexpr
在變數上和在函式上的行為並不一致. 對於變數來說, 如果被 constexpr
標識, 那麼它必定是編碼期已知的, 那麼它可以被用於標識陣列大小, 用在樣板引數上; 但是對於函式來說, 即使它被 constexpr
標識, 它也不是非要運作在編碼期, 而是可以在運作期執行. 因此, 我們要講語境分成兩個 : 編碼期語境和運作期語境.
被 constexpr
標識的函式, 如果存在某條陳述式在編碼期無法運作 (比如其呼叫的函式非 constexpr
函式或者某個變數在編碼期未知), 那麼整個函式會被推遲到運作期才運作; 否則, 函式的運作結果會在編碼期就產生. 相比較於 inline
, 編碼器在處理 constexpr
函式的時候, 會盡力使得其可以在編碼期就產生結果; 但是對於 inline
來說, 編碼器並不盡力, 你的 inline
請求可能會被編碼器忽略. 至於某個被 constexpr
標識的函式是否產生了編碼器就可以得到的結果, 可以將其的回傳值放入到樣板引數或者陣列宣告中. 如果沒有產生編碼錯誤, 那麼結果就是在編碼期就產生; 否則, 函式需要等到運作期才會執行.
如果沒有 constexpr
, 如果程式的某個地方要求編碼期語境的運作結果, 那麼此時我們還可能需要借助 template
來撰寫一個超函式.
在 C++ 11 中, 由于 constexpr
的严格限制, 大部分被 constexpr
標識的函式幾乎都可以在編碼期處理完成. 但是在 C++ 14 之後, constexpr
函式的限制被大大地放開, 大部分函式都可以被 constexpr
標識. 而在 C++ 20 之後, constexpr
的限制又被放開, 幾乎所有函式都可以被 constexpr
標識.
自創文章, 原著 : Jonny. 如若閣下需要轉發, 在已經授權的情況下請註明本文出處 :