[英]What makes a static variable initialize only once?
我注意到如果在代碼中初始化C ++中的靜態變量,初始化僅在您第一次運行該函數時運行。
這很酷,但是如何實現? 它是否轉化為某種扭曲的if語句? (如果給出一個值,那么..)
void go( int x )
{
static int j = x ;
cout << ++j << endl ; // see 6, 7, 8
}
int main()
{
go( 5 ) ;
go( 5 ) ;
go( 5 ) ;
}
是的,它通常會轉換為帶有內部布爾標志的隱式if
語句。 因此,在最基本的實現中,您的聲明通常會轉換為類似的內容
void go( int x ) {
static int j;
static bool j_initialized;
if (!j_initialized) {
j = x;
j_initialized = true;
}
...
}
最重要的是,如果您的靜態對象具有非平凡的析構函數,則該語言必須遵循另一個規則:這些靜態對象必須按其構造的相反順序進行破壞。 由於構造順序僅在運行時已知,因此銷毀順序也在運行時定義。 因此,每次使用非平凡的析構函數構造本地靜態對象時,程序必須將其注冊到某種線性容器中,以后它將用於按正確的順序銷毀這些對象。
不用說,實際細節取決於實施。
值得補充的是,當涉及使用編譯時常量初始化的“原始”類型的靜態對象(如示例中的int
)時,編譯器可以在啟動時自由初始化該對象。 你永遠不會注意到差異。 但是,如果您使用“非原始”對象采用更復雜的示例
void go( int x ) {
static std::string s = "Hello World!";
...
然后上面使用if
方法是你應該期望在生成的代碼中找到的,即使用編譯時常量初始化對象。
在您的情況下,初始化程序在編譯時是未知的,這意味着編譯器必須延遲初始化並使用隱式if
。
是的,編譯器通常會生成一個隱藏的布爾值“這已被初始化了嗎?” 標志和每次執行該函數時運行的if
。
這里有更多的閱讀材料: 編譯器如何實現靜態變量初始化?
雖然它確實是“某種扭曲的”,但扭曲可能比你想象的還要多......
ZoogieZork對AndreyT答案的評論涉及一個重要方面:靜態局部變量的初始化 - 在某些編譯器上包括GCC - 默認是線程安全的 (編譯器命令行選項可以禁用它)。 因此,它使用一些線程間同步機制(某種互斥或某種原子操作),這種機制可能相對較慢 。 如果你不熟悉 - 性能明智 - 在你的函數中明確使用這樣的操作,那么你應該考慮是否有一個影響較小的替代變量的懶惰初始化(即你自己以線程安全的方式明確地構造它)某處只有一次)。 很少有功能對性能非常敏感,但這很重要 - 不要讓它破壞你的一天,或者讓你的代碼更復雜,除非你的程序太慢而你的探測器指的是那個區域。
它們只被初始化一次,因為這是C ++標准所要求的。 如何發生這完全取決於編譯器供應商。 根據我的經驗,編譯器會生成並使用本地隱藏標志。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.