[英]zero initialization and static initialization of local scope static variable
我從Google閱讀了有關C ++初始化的幾篇文章,其中一些將我引到StackOverflow上。 我從這些帖子中挑選的概念如下:
我有一些關於初始化問題的查詢( 存儲類問題也可能與此有關):
myClass obj = myClass(100);
一樣引用初始化myClass obj = myClass(100);
或myClass obj = foo();
我對初始化和存儲類說明符問題有太多咨詢。 我閱讀了C ++ 2003 Standard文檔,但找不到清晰的邏輯,因為它們分散在整個文檔中。
我希望您能給我一個答案, 從邏輯上解釋存儲類說明符和初始化的整個過程。 歡迎任何參考!
可以解釋我的問題的代碼:
class myClass{
public:
int i;
myClass(int j = 10): j(i){}
// other declarations
};
myClass obj1;//global scope
static myClass obj2(2);//file scope
{ //local scope
myClass obj3(3);
static myClass obj4(4);
}
編輯 :
如果您認為我的問題很繁瑣,可以根據上述代碼幫助解釋您的想法。
我從Google閱讀了有關C ++初始化的幾篇文章,其中一些將我引到StackOverflow上。 我從這些帖子中挑選的概念如下:
- C ++的初始化順序為:
- 零初始化 ;
- 靜態初始化 ;
- 動態初始化 。
是的,確實有3個階段(在標准中)。 讓我們在繼續之前澄清它們:
一個簡單的例子:
int const i = 5; // constant initialization
int const j = foo(); // dynamic initialization
- 靜態對象 (包括變量)首先被零初始化 ,然后被靜態初始化 。
是的,沒有。
該標准要求首先將對象初始化為零,然后將它們初始化為:
注意:在進行常量初始化的情況下,編譯器可能會遵循as-if規則而忽略第一個零初始化的內存。
我有一些關於初始化問題的查詢( 存儲類問題也可能與此有關):
- 全局對象 (未使用static關鍵字定義)也是靜態對象,對嗎?
是的,在文件范圍內, static
對象只是符號的可見性 。 可以從另一個源文件中按名稱引用全局對象,而static
對象名稱完全位於當前源文件的本地。
混亂源於在許多不同情況下對世界static
的重用:
- 全局對象也像靜態對象一樣通過上述兩個步驟初始化,對嗎?
是的,實際上是本地靜態對象。
- 什么是靜態初始化 ? 它是否涉及初始化靜態對象(使用static關鍵字定義)?
不,如上所述,它是指在不執行用戶定義的函數的情況下初始化對象,而是在對象的內存上復制預先計算的字節模式。 請注意,對於稍后將被動態初始化的對象,這只是將內存清零。
- 我還讀到了在執行線程首次進入該塊時,使用static關鍵字在塊內(即在函數中)定義的對象已初始化! 這意味着本地靜態對象不會在執行主函數之前初始化。 這意味着它們沒有被初始化為上述兩個步驟,對嗎?
盡管實際上只有第一次執行通過了它們的定義,但它們是通過兩步過程進行初始化的。 因此,過程相同,但時間略有不同。
但是實際上,如果它們的初始化是靜態的(即,內存模式是編譯時模式)並且不占用其地址,則可以將它們優化。
請注意,在動態初始化的情況下,如果初始化失敗(本應初始化它們的函數會拋出異常),則下一次流控制通過它們的定義時,它將重新嘗試。
- 動態初始化是指由新操作員創建的對象的初始化,對嗎? 它可能像
myClass obj = myClass(100);
一樣引用初始化myClass obj = myClass(100);
或myClass obj = foo();
完全不是指需要執行用戶定義函數的初始化(注意:就C ++語言而言, std::string
具有用戶定義的構造函數)。
編輯:感謝Zach指向我,我錯誤地稱靜態初始化為C ++ 11標准稱為常量初始化; 現在應該修復此錯誤。
我相信有三個不同的概念:初始化變量,變量在內存中的位置,變量的初始化時間。
當在內存中分配變量時,典型的處理器會保持不變,因此該變量將具有與其他人之前存儲的值相同的值。 為了安全起見,一些編譯器添加了額外的代碼以初始化其分配為零的所有變量。 我認為這就是您所說的“零初始化”。 當您說:
int i; // not all compilers set this to zero
但是,如果您對編譯器說:
int i = 10;
然后編譯器指示處理器將10放入內存中,而不是保留舊值或將其設置為零。 我認為這就是您所說的“靜態初始化”。
最后,您可以這樣說:
int i;
...
...
i = 11;
然后處理器在執行int i;
時會“歸零初始化”(或保留舊值) int i;
然后當它到達第i = 11
行時,它會將變量“動態初始化”為11(第一次初始化后可能會發生很長時間。
有:基於堆棧的變量(有時稱為靜態變量)和內存堆變量(有時稱為動態變量)。
可以使用以下方法在堆棧段中創建變量:
int i;
或像這樣的內存堆:
int *i = new int;
不同之處在於,退出函數調用后,堆棧段變量丟失,而內存堆變量則保留,直到您說出delete i;
為止delete i;
。 您可以閱讀匯編語言書籍以更好地理解它們之間的區別。
當您輸入在其中定義的函數調用時,堆棧段變量是“零初始化的”或“靜態初始化的”。
當new
操作符首次創建內存堆變量時,該變量將被“零初始化”或“靜態初始化”。
您可以考慮一下static int i;
作為一個全局變量,范圍僅限於定義它的功能static int i;
之所以會這樣,是因為“靜態聽到”意味着另一件事(退出例程時它不會被破壞,因此它保留了其價值)。 我不確定,但我認為static int i;
的技巧是 是將其放入main()
的堆棧中,這意味着直到您退出整個程序(它保留第一個初始化),它才會被銷毀,或者它可能存儲在應用程序的數據段中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.