首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

Effective Modern C++ 條款 15:善用 constexpr 釋放編譯期計算潛能

     編輯:關於C++

constexpr 核心語意

constexpr 宣告的物件:不僅是 const,其值在編譯期可知。
constexpr 宣告的函式:若實參為編譯期常數,返回值在編譯期計算;否則退化為執行期普通函式。並不保證返回 const 或編譯期結果,這正是其威力所在——同一函式服務編譯期與執行期雙重場景。

constexpr 物件:編譯期常數的特權

int sz = 10;                    // 執行期變數
constexpr auto arraySize1 = sz; // 錯誤:sz 編譯期不可知
constexpr auto arraySize2 = 10; // 正確:10 為編譯期常數
std::array data; // 正確:arraySize2 可作模板參數

const auto arraySize3 = sz;     // 正確:const 不要求編譯期初始化
std::array data2; // 錯誤:arraySize3 編譯期不可知

所有 constexpr 物件皆為 const,但非所有 const 物件皆為 constexpr。 需編譯期常數的上下文(陣列大小、模板參數、枚舉值、對齊指定等)必須使用 constexpr。

constexpr 函式:雙重身份的威力

constexpr int pow(int base, int exp) noexcept {
    // C++14 寫法:迴圈、區域變數、多重 return 均合法
    auto result = 1;
    for (int i = 0; i < exp; ++i) result *= base;
    return result;
}

constexpr auto numConds = 5;
std::array results; // 編譯期計算 3^5 = 243

// 執行期調用同樣合法
auto base = readFromDB("base");
auto exp = readFromDB("exponent");
auto val = pow(base, exp); // 執行期計算

規則:實參皆為編譯期常數 → 編譯期計算;任一實參非編譯期常數 → 執行期計算。無需撰寫兩個版本。

字面值型別與使用者定義型別

內建型別(void 除外)皆為字面值型別。使用者定義型別若滿足:

  • 建構函式可為 constexpr
  • 成員函式可為 constexpr
  • 資料成員為字面值型別

則該型別亦為字面值型別,可用於 constexpr 語境:

class Point {
public:
    constexpr Point(double x = 0, double y = 0) noexcept : x(x), y(y) {}
    constexpr double xValue() const noexcept { return x; }
    constexpr double yValue() const noexcept { return y; }
    // C++14 允許 constexpr setter
    constexpr void setX(double newX) noexcept { x = newX; }
    constexpr void setY(double newY) noexcept { y = newY; }
private:
    double x, y;
};

constexpr Point p1(9.4, 27.7);
constexpr Point p2(28.8, 5.3);
constexpr Point mid = (p1 + p2) / 2; // 編譯期完成建構、存取、運算、回傳

constexpr 是介面承諾

一旦宣告為 constexpr,即承諾長期維持編譯期可計算特性。後期移除 constexpr 將破壞使用者代碼(如模板參數、常數表達式上下文)。不要為了 noexcept/constexpr 扭曲實現(如吞沒異常轉錯誤碼),得不償失。

總結

  1. constexpr 物件為 const 且編譯期初始化。
  2. constexpr 函式接受編譯期實參時編譯期計算,否則執行期計算。
  3. constexpr 物件/函式適用語境遠廣於非 constexpr 對應物。
  4. constexpr 是介面一部分,意味著長期承諾。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved