constexpr和常量表示式

baobaobashi發表於2024-05-07

1、常量表示式是什麼

在編譯時就能確定其值的表示式。換句話說,常量表示式的值在編譯過程中就已經是已知且不會改變的。常量表示式是由 資料型別初始值 共同決定的。(注意區分const 和 常量表示式)

常量表示式的特點:

  • 值在編譯時已知:常量表示式的值在編譯階段就能確定,而不是在執行時。
  • 不會改變:常量表示式的值一旦確定,就不會再改變。
  • 不包含函式呼叫:除了幾個特定的內建函式(如sizeof)外,常量表示式通常-不包含函式呼叫,因為函式呼叫可能會在執行時產生不同的結果。
  • 通常用於初始化常量:常量表示式常用於初始化常量,如陣列的大小、列舉值、constexpr變數等。

以下為幾個例子:

const int a1 = 10;      //a1為常量表示式
const int a2 = a1 + 10;     //a2為常量表示式
int a3 = 10;        //a3不為常量表示式,非const int型別
const int a4 = fun();   //需要執行時確定值,非編譯時期

2、constexpr

constexpr是C++中的一個關鍵字,用於指定常量表示式。
constexpr函式是能用於常量表示式的函式,它們的返回值型別所有形參的型別都必須是字面值型別,並且函式體中必須有且只有一條return語句。constexpr函式被隱式地指定為行內函數,以便在編譯過程中隨時展開。

int fun()
{
    return 10;
}

int main()
{
    constexpr int a = 10;
    constexpr int b = a + 10;
    constexpr int c = fun();        //error,fun函式必須是constexpr型別
    return 0;
}

constexpr int fun()
{
    
}

int main()
{
    constexpr int a = 10;
    constexpr int b = a + 10;
    constexpr int c = fun();    //error,fun函式必須有返回值
    return 0;
}

3、constexpr和指標

在C++中,constexpr用於指示一個值或表示式是常量表示式,它的值在編譯時是已知的且不會改變。

以下是關於constexpr和指標的一些要點:

  1. 指向常量的指標
    一個指標可以是constexpr,如果它指向的物件是常量,並且該指標在初始化後不會改變。但是,這並不保證所指向的物件的內容也是常量(只是指標本身是常量)。

    constexpr int* ptr = &a; // 指向常量的指標
    // 注意:a 必須是一個在編譯時已知地址的常量
    
  2. 指向字面量的指標
    指向字串字面量或其他字面量的指標也可以是constexpr,因為這些字面量的地址在編譯時是已知的。

    constexpr char* str = "Hello, constexpr!"; // 指向字串字面量的指標
    
  3. 指標的初始化
    constexpr指標必須在宣告時初始化,並且之後不能修改。

    constexpr int value = 42;
    constexpr int* ptr = &value; // 正確:在宣告時初始化
    ptr = &anotherValue; // 錯誤:不能修改constexpr指標
    
  4. 指標運算
    由於constexpr指標指向的值在編譯時是已知的,因此你不能對它們進行指標運算(如遞增或遞減),除非這些運算的結果在編譯時也是已知的。

  5. 指向陣列的指標
    你可以有一個constexpr指標指向陣列的首元素,但這並不意味著整個陣列都是constexpr。只有陣列的內容在編譯時已知,並且陣列本身被宣告為constexpr時,這樣的陣列才是constexpr陣列。

  6. 指向非常量資料的constexpr指標
    雖然技術上可以有一個constexpr指標指向非常量資料(即不是const的資料),但這樣做通常沒有太多意義,因為constexpr的主要目的是表示編譯時常量。

  7. constexpr函式和指標
    constexpr函式中,你可以返回指向常量資料的指標,但返回的指標必須指向在編譯時已知地址的物件。

    constexpr int* getPointer() {
        static int value = 42; // 靜態區域性變數具有固定的地址
        return &value;
    }
    

相關文章