簡體   English   中英

定義編譯時常量的最佳方法

[英]Best way of defining a compile-time constant

在C ++ 11中定義簡單常量值的最佳方法是什么,這樣就沒有運行時懲罰? 例如:(不是有效代碼)

// Not ideal, no type, easy to put in wrong spot and get weird errors
#define VALUE 123

// Ok, but integers only, and is it int, long, uint64_t or what?
enum {
     Value = 123
};

// Could be perfect, but does the variable take up memory at runtime?
constexpr unsigned int Value = 123;

class MyClass {
    // What about a constant that is only used within a class, so
    // as not to pollute the parent namespace?  Does this take up
    // memory every time the class is instantiated?  Does 'static'
    // change anything?
    constexpr unsigned int Value = 123;

    // What about a non-integer constant?
    constexpr const char* purpose = "example";
    std::string x;
    std::string metadata() { return this->x + (";purpose=" purpose); }
    // Here, the compiled code should only have one string
    // ";purpose=example" in it, and "example" on its own should not
    // be needed.
};

編輯

因為我被告知這是一個無用的問題,因為它背后沒有背景,這是背景。

我正在定義一些標志,以便我可以這樣做:

if (value & Opaque) { /* do something */ }

Opaque的值在運行時不會改變,因為只有在編譯時才需要它才能讓它在我的編譯代碼中結束。 這些值也用在一個循環中,該循環對圖像中的每個像素運行多次,所以我想避免運行時查找會降低它的速度(例如,內存訪問以在運行時檢索常量的值。)這不是'過早優化,因為算法目前需要大約一秒鍾來處理圖像,我經常有超過100個圖像要處理,所以我希望它盡可能快。

既然人們說這是微不足道的而且不用擔心它,我猜測#define就像你可以達到字面值一樣接近,所以也許這是避免“過度思考”問題的最佳選擇? 我想普遍的共識是你只希望沒有人需要使用Opaque這個詞或你想要使用的其他常量?

實際上,這比它看起來更棘手。

只是明確重申要求:

  1. 應該沒有運行時計算。
  2. 除實際結果外,不應有靜態,堆棧或堆內存分配。 (可執行代碼的分配不可能被禁止,但要確保CPU所需的任何數據存儲都是私有的。)

在C ++中,表達式可以是lvalues或prvalues(在C ++ 11和C之前, rvalues對應於相關概念)。 左值參考對象,因此它們可以在一個賦值表達式為L EFT-手側出現。 對象存儲和左值是我們想要避免的。

你想要的是一個標識符或id-expression來評估prvalue。

目前,只有普查員才能做到這一點,但正如您所觀察到的那樣,他們會留下一些需要的東西。 每個枚舉聲明都引入了一個新的,不同的類型,因此enum { Value = 123 }; 引入一個不是整數的常量,但它自己的唯一類型轉換int 這不是適合這項工作的合適工具,盡管它適用於工作。

你可以使用#define ,但這是一個黑客,因為它完全避免了解析器。 您必須使用所有大寫字母命名,然后確保相同的全大寫字母名稱不用於程序中的任何其他內容。 對於庫接口,這種保證尤其繁重。

下一個最佳選擇是函數調用:

constexpr int value() { return 123; }

但是,小心,因為constexpr函數仍然可以在運行時進行評估。 你需要跳過一個箍來表達這個值作為計算:

constexpr int value() {
    /* Computations that do not initialize constexpr variables
       (or otherwise appear in a constant expression context)
       are not guaranteed to happen at compile time, even
       inside a constexpr function. */

    /* It's OK to initialize a local variable because the
       storage is only temporary. There's no more overhead
       here than simply writing the number or using #define. */

    constexpr int ret = 120 + 3;
    return ret;
}

現在,您不能將常量稱為名稱,它必須是value() 函數調用運算符可能看起來效率較低,但它是完全消除存儲開銷的唯一當前方法。

你不能錯:

static constexpr const unsigned int Value = 123;

但老實說,盡量不要關心這一點。 喜歡,真的試試。

我認為您應該考慮C ++ 11為枚舉指定基礎類型的功能 ,適用於您的示例將是:

enum : unsigned int { Value = 123 };

這消除了您對使用枚舉的兩個異議之一,即您無法控制實際用於表示它們的類型。 但它仍然不允許非整數常量。

暫無
暫無

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

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