簡體   English   中英

C ++中函數內的靜態變量 - 即使函數沒有運行也會分配?

[英]Static variables within functions in C++ - allocated even if function doesn't run?

我一直在網上閱讀C ++,這是我無法找到答案的一件事。

我知道函數中使用的靜態變量類似於全局變量,並且該函數的后續調用將使靜態變量在調用之間保持其值。

但是,如果從未調用該函數,靜態變量是否會被分配?

謝謝

如果函數沒有被調用,很可能是你的連接將deadstrip兩者的功能和靜態變量,防止其進入.rodata.data ,或.bss段(或你的可執行文件格式的當量)。

但是,有多種原因導致鏈接器可能沒有死區(標志告訴它不能,無法確定取決於符號的內容等)。

值得檢查鏈接器映射文件(有時只是文本文件!),或者在最終可執行文件上使用objdumpnmdumpbin實用程序來查看符號或相關符號(例如靜態初始化代碼)是否存活。

C ++標准,第6.7節說:

具有靜態存儲持續時間(3.7.1)的所有本地對象的零初始化(8.5)在任何其他初始化發生之前執行。 具有使用常量表達式初始化的靜態存儲持續時間的POD類型(3.9)的本地對象在其首次輸入塊之前被初始化。 允許實現在允許實現靜態初始化具有命名空間范圍內的靜態存儲持續時間的對象的相同條件下,以靜態存儲持續時間執行其他本地對象的早期初始化(3.6.2)。 否則,在第一次控制通過其聲明時初始化這樣的對象; 這樣的對象在初始化完成時被認為是初始化的。

這表示本地靜態對象通常在控制流第一次遇到它們時初始化。 但是,它們可能在此之前被分配 - 除了參考靜態對象生存期之外,標准對靜態存儲實際上有些保持沉默。

C ++中的每個對象都有兩個與之關聯的嵌套時間段: 存儲持續時間生命周期 存儲持續時間是分配對象占用的原始內存的時間段。 生命周期是構造和破壞該存儲器中的實際對象之間的時間段。 (對於POD類型構造的對象 - 破壞要么無關緊要要么不適用,所以它們的壽命與它們的存儲持續時間相匹配)。

當有人說“已分配”時,他們通常會提到存儲時間 該語言實際上並未准確指定對象的存儲持續時間何時開始。 要求在對象的生命周期開始之前的某個時刻開始就足夠了。

因此,在一般情況下,函數內定義的靜態對象可能永遠不會從其生命周期開始,理論上,它的存儲持續時間也不必開始。 因此,理論上,甚至可能沒有“分配”。

但實際上,具有靜態存儲持續時間(“全局”,局部靜態等)的所有對象通常都是平等對待的:在程序啟動時,它們會在早期分配特定的存儲量。


另外需要注意的是,如果具有靜態存儲持續時間的本地對象需要進行非平凡的初始化,則在控件第一次通過定義時執行此初始化。 所以在這個例子中

void foo() {
  static int *p = new int[100];
}

如果永遠不調用該函數,則永遠不會分配動態數組。 如果調用該函數,它將只被分配一次。 這看起來不像你要問的,但我提到這是為了以防萬一。

我確信這將取決於實施。 MSVC的作用是 - 在EXE或DLL的自動數據段中分配靜態對象。 但是,構造函數僅在第一次執行包含靜態的函數時執行。

是的,實際分配是依賴於編譯器的,雖然我認為每個編譯器只保留可執行文件的.static段中的空間(或其可執行文件格式中的等價物)。
然而,初始化僅發生執行流遇到靜態對象的第一次,並且是標准所要求的。
static objects works in a different way, though. 但請注意, 靜態對象的初始化以不同的方式工作。 您可以在C ++ FAQ lite網站上獲得幾乎所有問題的非常好的答案。 我也喜歡Scott Meyers的“Effective C ++”。

要看。 如果你的意思是,永遠不會調用,因為函數實際上從未被調用過,那么你的編譯器可能不會分配它,甚至不會放入函數代碼。 但是,如果你讓它依賴於用戶輸入,並且用戶輸入恰好從未出現過,那么它可能會被預先分配。 但是,你正在這里的雷區中進行攻擊,最好只是假設它始終由時間控件進入引用它的函數創建。

在函數調用期間,在類(成員)或函數上定義的靜態變量不會在堆棧上動態分配,就像非靜態變量一樣。 它們被分配在為全局和靜態數據保留的生成代碼的另一個區域中。 因此,如果您是否調用該函數,實例化包含靜態成員的類,則無論如何都會在程序數據區保留其數據空間。

暫無
暫無

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

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