簡體   English   中英

我可以創建編譯時變量對象嗎?

[英]C++ - Can I create compile-time variable object?

我最近在使用constexpr,但我只是意識到我用錯了。 我很好奇我是否可以創建一個編譯時變量(或變量對象)。
來自cppreference.com的constexpr定義告訴我們:

constexpr說明符聲明可以在編譯時評估函數或變量的值。

那么為什么下面的代碼不正確?

#include <iostream>

int main()
{
    constexpr int x = 30;
    x += 10;
    std::cout << x;
}

該整數可以在編譯時完美評估。 我知道編譯器可以在沒有constexpr修飾符的情況下優化此類變量,但是如果我想擁有一個編譯時對象怎么辦?

#include <iostream>

class ctFoo {
public:
    ctFoo()
        : value{ 0 }
    {
    }
    int accumulate(int value_) {
        return (value += value_), value;
    }
    int value;
};

int main()
{
    ctFoo foo;
    std::cout << foo.accumulate(100);
}

我有什么把握可以在編譯時評估此代碼? 我之所以這么問,是因為我目前正在編寫一些Vector2和Vector3數學,並且我想創建這樣的實現,它將能夠處理編譯時和運行時計算。 可能嗎
謝謝。

編輯

正如max66所指出的,constexpr隱含const,但是我在問:為什么這樣? 現代編譯器應該能夠在編譯時推斷出它的價值。 另外,我知道我可以簡單地創建另一個constexpr常量(廣告最上面的代碼示例),但是我的問題是針對更復雜的代碼。

那么為什么下面的代碼不正確?

 #include <iostream> int main() { constexpr int x = 30; x += 10; std::cout << x; } 

constexpr暗示const 您需要將此約束到constexpr上下文中:

constexpr int foo() {
    int x = 30;
    x += 10;
    return x;
}

但是,如果我想擁有一個編譯時對象怎么辦?

 #include <iostream> class ctFoo { public: ctFoo() : value{ 0 } { } int accumulate(int value_) { return (value += value_), value; } int value; }; 

給它constexpr支持:

constexpr ctFoo() : value{ 0 }

constexpr int accumulate(int value_) {
    value += value_;
    return value;
}

現在的保證是,如果您的ctFoo對象是一個常量表達式,並且您在constexpr上下文(如foo函數示例)中調用accumulate ,那么您可以在編譯時使用結果。 例如:

constexpr int foo() {
    ctFoo f;
    f.accumulate(10);
    return f.value;
}

static_assert(foo() == 10);

要么:

constexpr void accumulate(ctFoo& f) {
    f.accumulate(10);
}

constexpr int foo() {
    ctFoo f;
    accumulate(f);
    return f.value;
}

static_assert(foo() == 10);

這里要記住的關鍵是,運行時評估也是一種選擇。 如果我將ctFoovalue設置為運行時值(例如,用戶輸入),那么在編譯時就不可能發生accumulate調用。 但這沒關系-相同的代碼在兩種情況下均有效。

您需要繼續閱讀:

對象聲明中使用的constexpr說明符暗含const

您不能更改constexpr ,這就是您可以在常量表達式中使用它的全部目的。

接下來要考慮的是,您似乎正在混合兩種不同的上下文。 我毫不懷疑,編譯器將能夠完全優化您的最后一個示例,但這就是constexpr所做的其他事情。 關鍵字表示它的含義可以在編譯時進行評估,但不一定必須如此。 因此,您可以編寫一個constexpr函數,其中的所有內容都可以在編譯時進行評估,並且仍然可以在運行時運行。

真正只有在編譯時就可以評估的對象(因此沒有優化程序),並且您可以修改的唯一時間是在編譯時上下文中。 您處於這樣的上下文中,例如constexpr函數中:

constexpr int foo() {
    int a = 10;
    ++a; // I can modify a.
    return a;
    // even if I did this: int Array[foo()];
}

但是您在常規功能中沒有這種能力,而該語言只是不允許這樣做。

因此,回答您的問題:

我有什么把握可以在編譯時評估此代碼?

您沒有任何東西,因為您沒有使用constexpr 即使這樣,如果您在不需要編譯時求值的地方調用constexpr函數,則該函數可能會在運行時被調用,

可能嗎

可以肯定的是,您已經創建了constexpr函數,如果需要,它將在編譯時進行評估。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM