關於C 中靜態的一點認識

2022-02-09 06:02:41 字數 2156 閱讀 1751

1.靜態直觀的特點

靜態成員最顯著的乙個特點就是它的作用域是全域性的。只要在呼叫處引入了對應的命名空間,那麼我們可以在**任何地方都可以直接使用。凡是具有全域性特徵的東西我們就可以考慮使用靜態。在實際的開發中,靜態字段我們常用實現資料的共享,修飾為靜態的方法當做常用的工具方法來使用。

2.命名上的思考

靜態從名稱的對立面上可以想到乙個詞叫動態,這裡所說的動態可以隱喻為例項成員。例項成員之所以可以形容為動態因為在記憶體中它的建立和釋放資源是根據例項化物件或gc(垃圾**)不斷變化的。而靜態成員在記憶體中很少會發生變化,靜態成員的建立是在第一次訪問對應的型別時進行的建立,資源釋放是在應用程式結束的時候。

3.靜態和例項(非靜態)的對比

靜態例項(非靜態)

需要static

關鍵字不需要static關鍵字

無法例項化只能使用類名呼叫

必須例項化物件後才能呼叫

在靜態方法中,可以訪問靜態成員

在例項方法中,可以訪問靜態成員

在靜態方法中不可以直接訪問例項成員,如需訪問需要建立物件

在例項方法中,可以直接訪問例項成員

呼叫前初始化(在建立第乙個例項或引用任何靜態成員之前)

例項化(呼叫建構函式

)物件時初始化

4.靜態成員的初始化的建立過程(本文重點)

當乙個類當中包含了靜態成員時,程式內部是如何初始化靜態成員的呢?

4.1**示例說明1

如執行上圖的程式,對於這種情況實際上即使是在程式執行時該類中的靜態成員是沒有被建立(初始化的

)。之所以是這種情況,因為程式中靜態成員對應的型別並沒有在任何位置出現過訪問該型別的**。而靜態成員的建立是在第一次訪問這個型別時建立的。

4.2**示例說明2

在遵循靜態成員的建立原則後,此圖對**進行改動後包含了對型別的訪問,那麼這個時候靜態成員是會被建立的。

從直觀的**上來看,很顯然會產生乙個對靜態成員初始化的誤解,因為**中的靜態成員在宣告時已經進行初始化賦值的操作。其實這種方式只是一種語法糖,是為了方便程式設計師給的簡單語法。實際上對於型別內部的字段賦值是通過建構函式來完成的。

我們現在思考乙個問題:上圖**中並沒有編寫任何的建構函式,那麼靜態成員是如何進行初始化賦值的呢?

通過一般的除錯時並看不出程式內部的執行過程,也很難找尋問題的答案。此處為了探尋上述的問題我可以通過反編譯工具檢視下上圖中反編譯後的**。如圖:

上圖中我們可以看到通過反編譯後myclass內部包含了乙個靜態的建構函式並且為靜態成員進行賦值。此處可以得到乙個結論:當在類中定義靜態成員的時候,實際上也定義了乙個靜態建構函式。

根據反編譯**的情況我們將靜態建構函式顯示的寫在**中除錯,來驗證下靜態建構函式是否被呼叫,然後觀察下例項成員和靜態成員初始化的順序。如圖:

根據上圖中的演示可以看出靜態建構函式被呼叫,並且會先呼叫靜態建構函式然後在呼叫例項建構函式。

5.關於靜態建構函式需要注意強調的幾點

靜態建構函式的定義上:不能有訪問修飾符並且必須無參,乙個類或結構當中只能有乙個建構函式,不允許過載和繼承。

靜態構造函式呼叫上:靜態建構函式在編寫**時不能像例項建構函式那樣直接呼叫,它的呼叫是由公共語言執行時(clr)呼叫。並且靜態建構函式只會呼叫一次。

以下**執行圖驗證靜態建構函式只會呼叫一次的情況:

使用建議:

盡量少使用靜態成員,因為靜態成員的生命週期是在應用程式結束後釋放的,然而gc(垃圾**)沒有對其進行記憶體的**管理。促使會上時間的占用記憶體,並且會產生一些記憶體垃圾。

學習感想:

看似使用簡單的靜態特性,有人運用設計出了軟體模式的單例模式。淬鍊堅實的基本功永遠都不算晚,個人覺得程式設計最難的是在運用,就算學會在高階的技術如果不會組合運用,也還是沒有達到真正掌握的程度。

關於C 中靜態的一點疑問

最近在學到c 來了,祝賀自己,但是也遇到兩個疑問 靜態指標 類的靜態成員以及靜態函式,當看到定義乙個靜態指標的時候,不知道我的邏輯思路 突發想到用定義乙個靜態 物件來代替。接下來 就是一段摸不著的邊際的苦苦思考和頭腦中建模。也查了很多資料,沒有相關說明,可能是我太愛鑽牛角了,但是我就是不能說服我那個...

關於C 引用型別一點認識

引用型別可以和指標一樣指向某個變數,但兩者在使用的時候還是有許多區別,1.宣告乙個引用型別後,一定要給他賦值,否則編譯通不過,特別是在類中,如果有引用成員變數時,一定要在建構函式的初始化列表中初始化,例如 class foo private int var foo f error,沒有初始化引用變數...

關於js中call apply的一點認識

function parent a,b function child a,b 從此以後,child具備召喚父親的能力,而父親也具備使用兒子的能力?為什麼呢?本質 替換了函式的上下文,通俗點,在parent的函式作用域內,this物件已經指代為child 物件,由此,parent中的this其實也是c...