簡體   English   中英

用可變值初始化靜態變量有哪些運行時間成本?

[英]What run-time costs are there to initializing a static with a variable value?

在C ++中,用合理的編譯器初始化帶有變量值而不是常量值的靜態變量的預期運行時間是多少?

例如,考慮以下代碼:

bool foo();
bool baz1() {
  const bool value = foo();
  static bool alternate1 = value;
  static bool alternate2 = false;

  // Do something.
  return alternate1;
}

alternate1alternate2之間的預期運行時成本差異是多少?

從編譯時常量(替代2)進行初始化很可能會在程序啟動期間發生,每次調用該函數都不會產生成本。

局部靜態變量的線程安全初始化將導致編譯器生成類似以下偽代碼的內容:

static bool alternate1;

static bool __initialised = false;
static __lock_type __lock;
if (!__initialised) {
    acquire(__lock);
    if (!__initialised) {
        alternate1 = value;
        __initialised = true;
    }
    release(__lock);
}

因此,每次調用該函數(可能涉及內存屏障或其他同步原語)時,都有可能對標志進行測試,並且首次獲取和釋放鎖會產生進一步的開銷。

請注意,在代碼中,無論變量是否已初始化,每次都會調用foo() 如果您將初始化更改為

static bool alternate1 = foo();

當然,細節取決於實現。 這是基於我對GCC生成的代碼的觀察。

static變量在程序開始時進行初始化,這意味着初始化只會發生一次。 僅一個布爾值的成本就非常低,而對於alternate1將是執行foo()的成本,在您的示例中這並不算多,因為它只是一個空函數。

概括地說,成本將是初始化基本類型(int,float等)或任何用戶定義類型/庫定義類型的初始化(運行ctor)的最大成本。 用函數初始化的任何static ,則最大值將是函數執行的成本。

看來,您的問題通常與靜態變量無關,而與在函數內部聲明的靜態變量有關。

從運行時值初始化此類變量的額外運行時成本來自多個來源

  1. 當控件第一次超過其聲明時(如果有的話),此類變量應僅初始化一次。 為了實現為每個此類變量分配一個附加的布爾變量/標志,並在每次控件通過聲明時進行檢查。 如果標志指示變量尚未初始化,則將其初始化。

  2. 對於那些具有非平凡析構函數的靜態變量,該語言必須保證在程序終止時其銷毀順序與它們的構造順序相反。 由於施工順序是在運行時確定的,因此程序必須准備一個運行時結構以計划將來的破壞。 對於具有非平凡析構函數的變量,這也作為步驟1的一部分完成:按構造順序將它們注冊在構造對象的“列表”中。 “列表”通常實現為預分配的數組(因為在編譯時已知其最大大小)。

  3. 在多線程配置中,上述步驟可能會/將伴隨其他鎖定/解鎖步驟。

由於這些都是在“幕后”實施的“家庭”支出,因此實際成本可能在很大程度上取決於實施。 查看/分析您的特定編譯器生成的代碼。

設置alternate1值將意味着調用該函數,即使該函數返回靜態值,也將必須保存堆棧,調用該函數,獲取其返回值,還原堆棧並將該值分配給變量。

從字面上看,在第一種情況下,您將執行至少8條匯編代碼行,而在第二種情況下,將僅執行一行。

暫無
暫無

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

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