Static關鍵字用法總結
static關鍵字是C, C++中都存在的關鍵字。static從字面理解,是“靜態的“的 意思,與此相對應的,應該是“動態的“。
static的作用主要有以下3個:
1、擴展生存期;
2、限制作用域;
3、唯一性;
1、擴展生存期
這一點主要是針對普通局部變量和static局部變量來說的。聲明爲static的局部變量的生存期不再是當前作用域,而是整個程序的生存期。
在程序中,常用內存類型主要有堆、棧和靜態存儲區。要理解static局部變量就必須首先理解這三種內存類型。
在C/C++中, 局部變量按照存儲形式可分爲三種auto, static, register
(譚浩強, 第174-175頁)
局部變量的默認類型都是auto,從棧中分配內存。
auto的含義是由程序自動控制變量的生存週期,通常指的就是變量在進入其作用域的時候被分配,離開其作用域的時候被釋放。
而static變量,不管是局部還是全局,都存放在靜態存儲區。
表面意思就是不auto,變量在程序初始化時被分配,直到程序退出前才被釋放;也就是static是按照程序的生命週期來分配釋放變量的,而不是變量自己的生命週期. 如果在main前設置斷點,然後查看static變量,已經被初始化,也就是說static在執行main函數前已經被初始化。也就是在程序初始化時被分配。
--------------------------------------------------------------------------------------------------------------------------
堆:由程序員自己分配釋放(用malloc和free,或new和delete) ,如果我們不手動釋放,那就要到程序結束才釋放。如果對分配的空間在不用的時候不釋放而一味的分配,那麼可能會引起內存泄漏,其容量取決於虛擬內存,較大。
棧:由編譯器自動分配釋放,其中存放在主調函數中被調函數的下一句代碼、函數參數和局部變量,容量有限,較小。
靜態存儲區:由在編譯時由編譯器分配,由系統釋放,其中存放的是全局變量、static變量和常量.
區別:
1) 堆是由低地址向高地址擴展,棧是由高地址向低地址擴展。
2) 堆是不連續的空間,棧是連續的空間。
3) 在申請空間後,棧的分配要比堆的快。對於堆,先遍歷存放空閒存儲地址的鏈表、修改鏈表、再進行分配;對於棧,只要剩下的可用空間足夠,就可分配到,如果不夠,那麼就會報告棧溢出。
4) 棧的生命期最短,到函數調用結束時;靜態存儲區的生命期最長,到程序結束時;堆中的生命期是到被我們手動釋放時(如果整個過程中都不手動釋放,那就到程序結束時)。
--------------------------------------------------------------------------------------------------------------------------
2、限制作用域
這一點相對於普通全局變量和static全局變量來說的。
對於全局變量而言,不論是普通全局 變量還是static全局變量,其存儲區都是靜態存儲區,因此在內存分配上沒有什麼區別。
區 別在於:
1) 普通的全局變量和函數,其作用域爲整個程序或項目,外部文件(其它cpp文件)可以通過extern關鍵字訪問該變量和函數。一般不提倡這種用法,如果要在多個cpp文件間共享數據,應該將數據聲明爲extern類型。
在頭文件裏聲明爲extern:
extern int g_value; // 注意,不要初始化值!
然後在其中任何一個包含該頭文件的cpp中初始化(一次)就好:
int g_value = 0; // 初始化一樣不要extern修飾,因爲extern也是聲明性關鍵字;
然後所有包含該頭文件的cpp文件都可以用g_value這個名字訪問相同的一個變量;
2) static全局變量和函數,其作用域爲當前cpp文件,其它的cpp文件不能訪問該變量和函數。如果有兩個cpp文件聲明瞭同名的全局靜態變量,那麼他們實際上是獨立的兩個變量。
static函數的好處是不同的人編寫不同的函數時,不用擔心自己定義的函數,是否會與其它文件中的函數同名。
頭文件中的static變量
如果在一個頭文件中聲明:
static int g_vaule = 0;
那麼會爲每個包含該頭文件的cpp都創建一個全局變量,但他們都是獨立的;所以也不建議這樣的寫法,一樣不明確需要怎樣使用這個變量,因爲只是創建了一組同名而不同作用域的變量。
3、數據唯一性
這是C++對static關鍵字的重用。主要指靜態數據成員/成員函數。
表示屬於一個類而不是屬於此類的任何特定對象的變量和函數. 這是與普通成員函數的最大區別, 也是其應用所在, 比如在對某一個類的對象進行計數時, 計數生成多少個類的實例, 就可以用到靜態數據成員. 在這裏面, static既不是限定作用域的, 也不是擴展生存期的作用, 而是指示變量/函數在此類中的唯一性. 這也是”屬於一個類而不是屬於此類的任何特定對象的變量和函數”的含義. 因爲它是對整個類來說是唯一的,因此不可能屬於某一個實例對象的. (針對靜態數據成員而言, 成員函數不管是否是static, 在內存中只有一個副本, 普通成員函數調用時, 需要傳入this指針, static成員函數調用時, 沒有this指針. )
static數據成員的初始化:
(1) 初始化在類體外進行,而前面不加static,以免與一般靜態變量或對象相混淆。
(2) 初始化時不加該成員的訪問權限控制符private,public等。
(3) 初始化時使用作用域運算符來標明它所屬類,因此,靜態數據成員是類的成員,而不是對象的成員。
(4) 靜態數據成員是靜態存儲的,它是靜態生存期,必須對它進行初始化。
Static成員函數
靜態成員函數和靜態數據成員一樣,它們都屬於類的靜態成員,它們都不是對象成員。因此,對靜態成員的引用不需要用對象名。
靜態成員函數僅能訪問靜態的數據成員,不能訪問非靜態的數據成員,也不能訪問非靜態的成員函數,這是由於靜態的成員函數沒有this指針。
reference:http://blog.csdn.net/ljinddlj/article/details/2495209