最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++中關鍵字constexpr的實現(xiàn)示例

 更新時間:2025年11月11日 10:08:09   作者:MzKyle  
constexpr是C++中用于編譯期計算的關鍵詞,它允許在編譯期確定值并進行安全檢查,從而提高編譯效率和代碼的健壯性,本文主要介紹了C++中關鍵字constexpr的實現(xiàn)示例,具有一定的參考價值,感興趣的可以了解一下

constexpr 是 C++11 引入并在后續(xù)標準(C++14/C++17/C++20)中持續(xù)增強的關鍵字,其核心作用是在編譯期計算常量或表達式,既保證了編譯期的安全性檢查,又能消除運行期計算的開銷,是實現(xiàn)“零成本抽象”和編譯期元編程的關鍵技術。

一、constexpr 的本質(zhì)與核心目標

constexpr 的字面意思是“常量表達式(constant expression)”,它的設計目標有兩個核心:

  1. 編譯期確定值:讓變量、函數(shù)或?qū)ο蟮娜≈翟诰幾g階段就能計算完成,避免運行時的冗余計算(如重復的數(shù)學運算、常量初始化)。
  2. 強類型安全檢查:強制編譯器驗證“是否滿足編譯期計算條件”,若存在運行時依賴(如動態(tài)輸入、未初始化變量),則直接報錯,避免潛在的邏輯錯誤。

從本質(zhì)上看,constexpr 是對“常量”概念的強化——它不僅要求值“不可修改”,更要求值“可在編譯期確定”,這是它與傳統(tǒng) const 最核心的區(qū)別。

二、constexpr 變量:編譯期初始化的常量

constexpr 最基礎的用法是修飾變量,要求變量在編譯期完成初始化,且后續(xù)不可修改。

1. 變量聲明的核心要求

  • 必須在聲明時初始化,且初始化表達式必須是常量表達式(即無運行時依賴的表達式)。
  • 變量類型必須是“字面類型(Literal Type)”——即能通過 constexpr 構(gòu)造函數(shù)初始化、無虛函數(shù)/虛基類、成員均為字面類型的類型(如 int、double、數(shù)組、滿足條件的自定義類)。

正確示例

// 1. 基本類型:編譯期計算 3+2 的結(jié)果(值為5)
constexpr int a = 3 + 2;
// 2. 數(shù)組:大小由 constexpr 變量確定(編譯期已知)
constexpr size_t arr_size = 10;
int arr[arr_size]; // 合法,數(shù)組大小編譯期確定
// 3. 常量表達式嵌套:依賴其他 constexpr 變量
constexpr int b = a * 4; // 編譯期計算 5*4=20

錯誤示例

int x = 5;
// 錯誤:初始化表達式依賴運行時變量 x(非常量表達式)
constexpr int c = x + 3; 
// 錯誤:未初始化(constexpr 變量必須聲明時初始化)
constexpr double d; 

2. 修飾指針與引用的特殊規(guī)則

constexpr 修飾指針/引用時,需明確“修飾的是指針本身”還是“指向的對象”,規(guī)則與 const 類似,但要求更嚴格(必須編譯期確定地址):

  • constexpr 指針:指針本身是編譯期常量(地址固定),指向的對象是否可修改需額外用 const 聲明。
    int num = 10;
    // 錯誤:num 是棧上變量(地址運行時確定),無法作為 constexpr 指針的目標
    constexpr int* p1 = # 
    
    // 正確:全局變量地址編譯期確定,p2 是 constexpr 指針(地址固定)
    int global_num = 20;
    constexpr int* p2 = &global_num; 
    // 正確:constexpr 指針 + const 對象(指針地址固定,指向的內(nèi)容不可改)
    constexpr const int* p3 = &global_num; 
    
  • constexpr 引用:引用的目標必須是編譯期常量(地址固定),且引用本身不可重新綁定(與 const 引用一致,但要求更高)。
    // 正確:引用目標是 constexpr 變量(編譯期常量)
    constexpr int e = 5;
    constexpr const int& ref = e; 
    

三、constexpr 函數(shù):編譯期可執(zhí)行的函數(shù)

constexpr 函數(shù)是支持“編譯期調(diào)用”的函數(shù)——當函數(shù)的實參是常量表達式時,函數(shù)會在編譯期計算結(jié)果;若實參是運行時變量,則退化為普通函數(shù)在運行期執(zhí)行(即“兩態(tài)性”)。

const修飾的函數(shù)(修飾函數(shù)返回值或者函數(shù)類型)不可以因為constexpr的存才而刪除,起到的作用不同,constexpr修飾作用可退回普通函數(shù),但是const修飾的函數(shù)必定是常函數(shù)。

1. 函數(shù)聲明的核心要求(隨標準演進放寬)

constexpr 函數(shù)的限制在 C++11 到 C++20 中逐步放寬,核心要求如下:

標準版本核心限制允許的操作
C++111. 函數(shù)體僅允許 return 語句
2. 不能有局部變量/循環(huán)
3. 返回值和參數(shù)必須是字面類型
僅常量表達式計算、return
C++141. 允許定義局部變量(需是字面類型,可初始化)
2. 允許循環(huán)(for/while)
3. 允許條件判斷(if/else)
局部變量、循環(huán)、條件判斷、常量計算
C++171. 允許 constexpr lambda(嵌套使用)
2. 允許使用部分標準庫函數(shù)(如 std::string_view)
lambda、部分標準庫調(diào)用
C++201. 允許動態(tài)內(nèi)存分配(new/delete,但需在編譯期釋放)
2. 允許使用 std::vector/std::string(部分實現(xiàn))
3. 允許 try-catch(僅編譯期異常)
動態(tài)內(nèi)存(編譯期釋放)、復雜容器、異常處理

2. 典型示例:編譯期計算階乘

// C++14 及以上:constexpr 函數(shù)支持循環(huán)
constexpr int factorial(int n) {
    if (n < 0) throw "n must be non-negative"; // C++20 允許 try-catch
    int result = 1;
    for (int i = 1; i <= n; ++i) {
        result *= i;
    }
    return result;
}

// 1. 編譯期調(diào)用:實參是常量表達式(5),結(jié)果在編譯期計算為 120
constexpr int f5 = factorial(5); 
// 2. 運行期調(diào)用:實參是運行時變量(x),結(jié)果在運行期計算
int x = 6;
int f6 = factorial(x); 

3. 關鍵特性:兩態(tài)性與編譯期驗證

  • 兩態(tài)性:constexpr 函數(shù)并非“必須編譯期執(zhí)行”,而是“可編譯期執(zhí)行”。實參是常量表達式時編譯期計算,否則運行期計算,兼顧靈活性與性能。
  • 編譯期驗證:若強制要求函數(shù)在編譯期執(zhí)行(如賦值給 constexpr 變量),編譯器會嚴格檢查——若函數(shù)存在無法編譯期執(zhí)行的操作(如依賴運行時輸入),則直接報錯。

四、constexpr 類與對象:編譯期構(gòu)造的自定義類型

C++11 允許類通過 constexpr 構(gòu)造函數(shù) 創(chuàng)建“編譯期對象”,即對象的所有成員在編譯期初始化,且對象的成員函數(shù)可通過 constexpr 修飾實現(xiàn)編譯期調(diào)用。

1. constexpr 構(gòu)造函數(shù)的要求

  • 必須初始化類的所有非靜態(tài)成員(確保無未初始化成員)。
  • C++11 中函數(shù)體必須為空(僅通過初始化列表初始化);C++14 及以上允許簡單函數(shù)體(如條件判斷)。
  • 構(gòu)造函數(shù)的參數(shù)必須是字面類型。

示例:編譯期可構(gòu)造的 Point 類

class Point {
private:
    int x_, y_;
public:
    // C++11 風格:空函數(shù)體,通過初始化列表初始化成員
    constexpr Point(int x, int y) : x_(x), y_(y) {}
    
    // constexpr 成員函數(shù):編譯期計算兩點距離的平方
    constexpr int distance_sq(const Point& other) const {
        int dx = x_ - other.x_;
        int dy = y_ - other.y_;
        return dx*dx + dy*dy;
    }
    
    // 普通成員函數(shù):僅運行期調(diào)用
    void print() const {
        std::cout << "(" << x_ << "," << y_ << ")\n";
    }
};

// 1. 編譯期創(chuàng)建對象:構(gòu)造函數(shù)實參是常量表達式
constexpr Point p1(1, 2);
constexpr Point p2(4, 6);
// 2. 編譯期調(diào)用成員函數(shù):計算距離平方(結(jié)果 25)
constexpr int dist_sq = p1.distance_sq(p2); 
// 3. 運行期調(diào)用普通成員函數(shù)
p1.print(); 

2. constexpr 對象的特性

  • constexpr 對象的所有非靜態(tài)成員均為編譯期常量,可直接用于常量表達式(如作為 constexpr 函數(shù)的實參)。
  • constexpr 對象的 this 指針在編譯期可見,因此其 constexpr 成員函數(shù)可直接訪問成員并完成編譯期計算。

五、C++17/C++20 關鍵增強:constexpr lambda、consteval 與 constinit

隨著標準演進,constexpr 的能力大幅擴展

1. C++17:constexpr lambda

C++17 允許 lambda 表達式通過 constexpr 修飾(或隱式滿足 constexpr 條件),使其可在編譯期執(zhí)行。

示例:編譯期使用 lambda 計算數(shù)組總和

#include <array>

constexpr auto sum_array = [](const auto& arr) {
    int sum = 0;
    for (auto val : arr) {
        sum += val;
    }
    return sum;
};

// 編譯期計算數(shù)組總和:sum = 1+2+3+4+5 = 15
constexpr std::array<int, 5> arr = {1,2,3,4,5};
constexpr int total = sum_array(arr); 

2. C++20:consteval 與 constinit

C++20 新增兩個關鍵字,進一步細化“編譯期計算”的語義,與 constexpr 形成互補:

  • consteval:強制函數(shù)“必須在編譯期執(zhí)行”(即“立即函數(shù)”),若無法編譯期計算(如實參是運行時變量),直接報錯。
    // consteval 函數(shù):必須編譯期執(zhí)行
    consteval int square(int n) {
        return n * n;
    }
    
    constexpr int s4 = square(4); // 正確:編譯期計算(16)
    int y = 5;
    // 錯誤:實參 y 是運行時變量,無法編譯期執(zhí)行
    int s5 = square(y); 
    
  • constinit:確保變量“在編譯期初始化”(僅適用于靜態(tài)/線程局部變量),但不要求變量是“常量”(即后續(xù)可修改,只要初始化在編譯期完成)。
    // 錯誤:靜態(tài)變量默認運行時初始化(全局變量除外)
    static int static_num = 10; 
    // 正確:constinit 強制靜態(tài)變量編譯期初始化(值 20)
    constinit static int constinit_num = 20; 
    constinit_num = 30; // 合法:constinit 僅限制初始化,不限制后續(xù)修改
    

constexpr、consteval、constinit 對比

關鍵字核心語義是否允許運行期執(zhí)行適用場景
constexpr可編譯期執(zhí)行(兩態(tài)性)是(實參為運行時變量時)兼顧編譯期計算與運行期靈活調(diào)用
consteval必須編譯期執(zhí)行(強制)否(否則報錯)確保零運行時開銷(如編譯期哈希)
constinit強制編譯期初始化是(變量可后續(xù)修改)靜態(tài)變量的編譯期初始化(如全局配置)

六、constexpr 的核心應用場景

constexpr 并非“語法糖”,而是解決實際問題的工具,核心應用場景包括:

1. 編譯期計算:消除運行時開銷

對于固定邏輯(如數(shù)學公式、常量配置),通過 constexpr 在編譯期計算結(jié)果,避免運行時重復計算。例如:

  • 編譯期計算數(shù)組大?。ㄌ娲?sizeof(arr)/sizeof(arr[0]))。
  • 編譯期生成哈希值(如字符串字面量的哈希,避免運行時哈希計算)。

2. 靜態(tài)斷言(static_assert):編譯期合法性檢查

static_assert 的條件必須是常量表達式,constexpr 可提供復雜的編譯期條件判斷,實現(xiàn)更靈活的斷言。例如:

// 編譯期檢查模板參數(shù)是否為偶數(shù)
template <int N>
void process() {
    static_assert(N % 2 == 0, "N must be even"); // 條件依賴 constexpr 計算
}

process<4>(); // 正確:4 是偶數(shù)
// process<5>(); // 錯誤:編譯期斷言失敗,提示 "N must be even"

3. 編譯期元編程:生成代碼邏輯

結(jié)合模板與 constexpr,可在編譯期生成代碼(如循環(huán)展開、類型判斷),實現(xiàn)“元編程”。例如:

  • 編譯期遍歷數(shù)組并計算結(jié)果(無需運行時循環(huán))。
  • 編譯期根據(jù)類型生成不同的處理邏輯(替代運行時 if-else)。

4. 常量表達式接口:增強類型安全

通過 constexpr 定義接口(如 constexpr 函數(shù)、constexpr 類),強制調(diào)用者使用編譯期常量,避免運行時錯誤。例如:

  • 自定義數(shù)值類型(如角度、長度),通過 constexpr 構(gòu)造函數(shù)確保輸入合法(如角度范圍 0-360)。

七、常見誤區(qū)與注意事項

  1. “constexpr 變量一定在編譯期存儲”:錯誤。constexpr 僅要求“值在編譯期確定”,存儲位置仍由編譯器決定(如可能存儲在數(shù)據(jù)段,也可能直接內(nèi)聯(lián)到代碼中)。
  2. “constexpr 函數(shù)只能返回常量”:錯誤。constexpr 函數(shù)的返回值是否為常量,取決于實參——實參是常量表達式時返回常量,實參是運行時變量時返回普通值。
  3. “constexpr 與 const 完全等價”:錯誤。const 僅表示“值不可修改”,不要求“值在編譯期確定”(如 const int a = rand(); 是合法的,但 constexpr int a = rand(); 是錯誤的);而 constexpr 同時要求“不可修改”和“編譯期確定”。
  4. “C++20 后 constexpr 可隨意使用動態(tài)內(nèi)存”:錯誤。C++20 允許 constexpr 函數(shù)使用 new,但必須在編譯期通過 delete 釋放(否則編譯器報錯),無法將動態(tài)內(nèi)存泄露到運行時。

補充const與constexpr

constconstexpr 修飾函數(shù)時的作用和場景完全不同,核心區(qū)別在于:const 關注函數(shù)是否修改對象狀態(tài)(僅用于成員函數(shù)),而 constexpr 關注函數(shù)是否能在編譯時求值(可用于任意函數(shù))。

1.const修飾函數(shù)(僅適用于類的非靜態(tài)成員函數(shù))

  • 作用:聲明該成員函數(shù)是“常量成員函數(shù)”,承諾不會修改對象的非靜態(tài)數(shù)據(jù)成員,也不能調(diào)用非 const 的成員函數(shù)(防止間接修改對象)。
    本質(zhì)是對函數(shù)的“行為約束”,確保調(diào)用該函數(shù)時對象狀態(tài)不變,屬于運行時的類型安全保障。

  • 語法const 放在函數(shù)參數(shù)列表后(const 成員函數(shù)的標志)。

    class A {
    private:
        int x;
    public:
        // const 成員函數(shù):承諾不修改 x,也不能調(diào)用非 const 函數(shù)
        int getX() const { 
            // x = 10;  // 編譯錯誤:const 函數(shù)不能修改成員
            return x; 
        }
    
        void setX(int val) {  // 非 const 函數(shù):可以修改成員
            x = val; 
        }
    };
    
  • 適用場景
    當需要獲取對象狀態(tài)(如訪問器 getter)但不修改它時,用 const 修飾,確保函數(shù)的“只讀”行為。
    例如:const A a; a.getX(); 合法(const 對象只能調(diào)用 const 成員函數(shù)),但 a.setX(5); 會報錯。

2.constexpr修飾函數(shù)(適用于任意函數(shù):普通函數(shù)、成員函數(shù)、構(gòu)造函數(shù)等)

  • 作用:聲明該函數(shù)是“常量表達式函數(shù)”,可以在編譯時被求值(前提是輸入?yún)?shù)為常量表達式)。
    本質(zhì)是對函數(shù)的“計算時機約束”,允許函數(shù)結(jié)果作為編譯期常量使用(如模板參數(shù)、數(shù)組大小等),屬于編譯時的計算能力保障。

  • 語法constexpr 放在函數(shù)返回類型前。

    // 普通 constexpr 函數(shù):編譯時可求值
    constexpr int add(int a, int b) {
        return a + b;
    }
    
    class B {
    private:
        int y;
    public:
        // constexpr 構(gòu)造函數(shù):允許創(chuàng)建編譯期對象
        constexpr B(int val) : y(val) {}
    
        // constexpr 成員函數(shù):編譯時可求值(需滿足條件)
        constexpr int getY() const {  // 可同時是 const(雙重約束)
            return y;
        }
    };
    
  • 適用場景
    當需要在編譯時計算結(jié)果(如常量、模板參數(shù))時,用 constexpr 修飾。例如:

    constexpr int sum = add(3, 5);  // 編譯時計算,sum 是編譯期常量(8)
    constexpr B b(10);             // 編譯期創(chuàng)建對象
    int arr[b.getY()];             // 合法:數(shù)組大小是編譯期常量(10)
    

    注意:constexpr 函數(shù)并非只能在編譯時調(diào)用,當輸入?yún)?shù)是運行時變量時,它也能像普通函數(shù)一樣在運行時調(diào)用。

3. 核心對比表

維度const 修飾函數(shù)constexpr 修飾函數(shù)
適用范圍僅類的非靜態(tài)成員函數(shù)任意函數(shù)(普通函數(shù)、成員函數(shù)、構(gòu)造函數(shù)等)
核心作用保證函數(shù)不修改對象狀態(tài)(只讀約束)保證函數(shù)可在編譯時求值(編譯期計算)
本質(zhì)運行時的對象狀態(tài)保護編譯時的計算能力支持
與常量表達式的關系無關(結(jié)果不能直接作為編譯期常量)直接相關(結(jié)果可作為編譯期常量)
能否同時使用可以(constexpr const 成員函數(shù),雙重約束)無沖突,constexpr 不影響 const 的作用
  • const 修飾成員函數(shù):告訴編譯器和使用者“這個函數(shù)不會改對象,放心在 const 對象上調(diào)用”。
  • constexpr 修飾函數(shù):告訴編譯器“這個函數(shù)可以在編譯時算,給我編譯期優(yōu)化的能力”。
  • 兩者可以共存(如 constexpr const 成員函數(shù)),此時函數(shù)既保證不修改對象,又能在編譯時求值。

到此這篇關于C++中關鍵字constexpr的實現(xiàn)示例的文章就介紹到這了,更多相關C++ 關鍵字constexpr內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家! 

相關文章

  • C++根據(jù)傳入的函數(shù)指針來解析需要的參數(shù)(推薦)

    C++根據(jù)傳入的函數(shù)指針來解析需要的參數(shù)(推薦)

    C++可以根據(jù)傳入的函數(shù)指針,獲取自己需要的參數(shù)類型,然后根據(jù)參數(shù)源中獲取需要的參數(shù),具體實現(xiàn)方式大家參考下本文
    2018-05-05
  • C++ 數(shù)據(jù)結(jié)構(gòu)之對稱矩陣及稀疏矩陣的壓縮存儲

    C++ 數(shù)據(jù)結(jié)構(gòu)之對稱矩陣及稀疏矩陣的壓縮存儲

    這篇文章主要介紹了C++ 數(shù)據(jù)結(jié)構(gòu)之對稱矩陣及稀疏矩陣的壓縮存儲的相關資料,這里實現(xiàn)稀疏矩陣和對稱矩陣的壓縮存儲的實例,需要的朋友可以參考下
    2017-08-08
  • C語言中strlen()函數(shù)的使用詳解

    C語言中strlen()函數(shù)的使用詳解

    strlen函數(shù)是用來求字符串長度的函數(shù),這個函數(shù)遇到‘\0’就會停止,且這個長度不包含‘\0’,這篇文章給大家介紹了C語言中strlen()函數(shù)的使用,感興趣的朋友一起看看吧
    2024-02-02
  • 用C語言求解第N項斐波那契數(shù)列問題

    用C語言求解第N項斐波那契數(shù)列問題

    這篇文章主要介紹了用C語言求解第N項斐波那契數(shù)列問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • C語言scanf,fscanf和sscanf的區(qū)別

    C語言scanf,fscanf和sscanf的區(qū)別

    每種語言都對正則表達式有著不同程度的支持,在C語言中,有輸入功能的這三個函數(shù)對正則表達式的支持并不強大,但是我們還是有必要了解一下
    2021-10-10
  • C語言實現(xiàn)分治法實例

    C語言實現(xiàn)分治法實例

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)分治法的實例,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • C語言strcat函數(shù)詳解:字符串追加的利器

    C語言strcat函數(shù)詳解:字符串追加的利器

    strcat函數(shù)用于將源字符串追加到目標字符串的末尾,并返回一個指向目標字符串的指針,它可以實現(xiàn)字符串的拼接操作
    2024-08-08
  • C++如何實現(xiàn)廣義表詳解

    C++如何實現(xiàn)廣義表詳解

    廣義表是非線性結(jié)構(gòu),其定義是遞歸的。那么下面跟著小編一起看看如何用C++實現(xiàn)廣義表,有需要的可以參考借鑒。
    2016-08-08
  • 淺談C++ 虛函數(shù)

    淺談C++ 虛函數(shù)

    這篇文章主要介紹了C++ 虛函數(shù)的相關資料,幫助大家更好的理解和學習c++,感興趣的朋友可以了解下
    2020-09-09
  • C語言實現(xiàn)簡單的推箱子小游戲

    C語言實現(xiàn)簡單的推箱子小游戲

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)簡單的推箱子小游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07

最新評論

麻城市| 灵台县| 金堂县| 浮梁县| 元氏县| 南木林县| 荣成市| 渝北区| 望谟县| 纳雍县| 荆门市| 无为县| 铁力市| 南开区| 朝阳县| 北辰区| 大厂| 凭祥市| 太康县| 锦州市| 曲靖市| 长沙县| 关岭| 眉山市| 衢州市| 万荣县| 合江县| 龙江县| 定边县| 永福县| 大洼县| 福泉市| 北票市| 海阳市| 合水县| 凤阳县| 重庆市| 灌云县| 盐亭县| 镶黄旗| 阜新市|