static關鍵字的用途總結


要面試了,復習一下c++的語言細節,才發現自己差的還很多。

static int i1=1;
static int i2=1;
int i3;
static int i4;
int main()
{
    static int i5=1;
    int i6=1;
    int i7;
    cout<<&i1<<" "<<i1<<endl;
    cout<<&i2<<" "<<i2<<endl;
    cout<<&i3<<" "<<i3<<endl;
    cout<<&i4<<" "<<i4<<endl;
    cout<<&i5<<" "<<i5<<endl;
    cout<<&i6<<" "<<i6<<endl;
    cout<<&i7<<" "<<i7<<endl;
    getchar();
}

輸出:

 

 

 首先說值:

普通/static全局變量(i3)默認初始化為0,普通局部變量初始值未定義(i7)

static局部變量即靜態局部變量,也會初始化為0

再說內存存儲位置:

先放個進程的內存圖:

 

 

其中未初始化+初始化區域就是靜態區。注意靜態區和常量區還不一樣,常量比如:int a=1;的1。或者char* x="123";的“123”。

 

 

 對應這兩張圖來看就很清晰了

 

 

好,下面進入主題:

全局變量都在靜態變量區,不管是不是static

注意未初始化的和未初始化的不在一起的!證據如下,其中第一行的都是帶初始化的,第二行不帶初始化的,明顯可見未初始化的bss段地址比已經初始化的數據段地址更大,更靠上:

 

 

普通局部變量在棧區/堆區,static局部變量在靜態變量區。

 

static的不同用法:

1.static全局變量/函數,因為函數肯定是全局的了,所以這倆捏一起說。

只有一個用途:不讓其他cpp使用自己,即限制作用域為所在的cpp。如果不帶static,其他cpp可以extern修飾進而引用。

所以假設a.cpp里有一個函數f。

如果我們讓其他cpp引用這個f函數。那么我們應該把f的聲明加入到a.cpp的頭文件並且聲明時不要加static,這樣會導致每個包含a.h的cpp都有一份該函數f的副本,大大增加編譯效率!當然這個問題回頭另外寫一篇博客,就先點到為止。另外永遠不要在頭文件中定義變量!

如果我們不想讓其他cpp引用f函數,則我們直接在f的定義前加上static修飾,這樣其他cpp就看不到f函數了(即使包含a頭文件的情況下也是看不到的)。

2.static局部變量,如:

void f(){
    static int cnt=0;cnt++;
}

這個函數調用幾次,cnt就等於幾。

static局部變量和全局變量一起存在靜態變量區,二者唯一的區別就是:static局部變量作用域只限於所在的函數,但到達函數以外時並不會釋放,而是會保持已有的值繼續等待下次調用。

static局部變量只會初始化一次!直到cpp退出才會釋放。

3.類中的static成員變量(類的靜態成員變量):

static成員變量分配在靜態區。

在所有該類的實例(對象)中只存在一個副本,所有對象共享一個該靜態變量。

類的靜態成員變量需要在類中聲明,類外定義,例子如下:

class A{
    static int x;
};
int A::x=1;

 

4.類中的static成員函數:

Static修飾的成員函數,在代碼區分配內存。只能調用靜態成員變量,別的和普通成員函數區別不大。

概括來說:類的靜態成員函數、變量的存儲位置不在類里,所以也就理所當然的沒有this指針。所以靜態成員函數無法調用普通成員變量也就合理了(因為沒有this指針,根本找不到相應的變量位置!)。

由於二者都與類綁定,而不與特定對象綁定,所以二者可以除了可以通過對象訪問外,還可以通過類名訪問(A:: f();)。

另外注意:靜態成員函數不能加const限定,可能是因為靜態成員函數本身就不會改變類內部數據。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM