static 和 儲存區

2021-06-11 01:14:11 字數 3851 閱讀 7152

static 資料型別用來給變數建立永久儲存空間.靜態變數在函式間呼叫時保持他們的值不變.當用在乙個類中時,所有要用到靜態變數的時候這個類將把這個變數映象過去.

c#與c++的static有兩種用法:面向過程程式設計中的static和物件導向程式設計中的static。前者應用於普通變數和函式,不涉及類;後者主要說明static在類中的作用。

在全域性變數前,加上關鍵字static,該變數就被定義成為乙個靜態全域性變數。我們先舉乙個靜態全域性變數的例子,如下:

//example 1

#include void fn();

static int n; //定義靜態全域性變數

void main()

void fn()

void fn()//定義靜態函式

;int myclass::sum=0;//定義並初始化靜態資料成員

myclass::myclass(int a,int b,int c)

void myclass::getsum()

; p(int i):a(i){};

void setstatic(int i)

void printmem()

;int myclass::sum=0;//定義並初始化靜態資料成員

myclass::myclass(int a,int b,int c)

void myclass::getsum() //靜態成員函式的實現

{ // cout<;)為乙個類的物件或指向類物件的指標呼叫靜態成員函式,也可以直接使用如下格式:

《類名》::《靜態成員函式名》(《參數列》)

呼叫類的靜態成員函式。

作用static靜態變數宣告符。在宣告它的程式塊,子程式塊或函式內部有效,值保持,在整個程式期間分配儲存器空間,編譯器預設值0。

是c++中很常用的修飾符,它被用來控制變數的儲存方式和可見性。

為什麼要引入static

函式內部定義的變數,在程式執行到它的定義處時,編譯器為它在棧上分配空間,大家知道,函式在棧上分配的空間在此函式執行結束時會釋放掉,這樣就產生了乙個問題: 如果想將函式中此變數的值儲存至下一次呼叫時,如何實現? 最容易想到的方法是定義乙個全域性的變數,但定義為乙個全域性變數有許多缺點,最明顯的缺點是破壞了此變數的訪問範圍(使得在此函式中定義的變數,不僅僅受此函式控制)。

什麼時候用static

需要乙個資料物件為整個類而非某個物件服務,同時又力求不破壞類的封裝性,即要求此成員隱藏在類的內部,對外不可見。

static的內部機制

靜態資料成員要在程式一開始執行時就必須存在。因為函式在程式執行中被呼叫,所以靜態資料成員不能在任何函式內分配空間和初始化。

這樣,它的空間分配有三個可能的地方,一是作為類的外部介面的標頭檔案,那裡有類宣告;二是類定義的內部實現,那裡有類的成員函式定義;三是應用程式的main()函式前的全域性資料宣告和定義處。

靜態資料成員要實際地分配空間,故不能在類的宣告中定義(只能宣告資料成員)。類宣告只宣告乙個類的「尺寸和規格」,並不進行實際的記憶體分配,所以在類宣告中寫成定義是錯誤的。它也不能在標頭檔案中類宣告的外部定義,因為那會造成在多個使用該類的原始檔中,對其重複定義。

static被引入以告知編譯器,將變數儲存在程式的靜態儲存區而非棧上空間,靜態

資料成員按定義出現的先後順序依次初始化,注意靜態成員巢狀時,要保證所巢狀的成員已經初始化了。消除時的順序是初始化的反順序。

static的優勢

可以節省記憶體,因為它是所有物件所公有的,因此,對多個物件來說,靜態資料成員只儲存一處,供所有物件共用。靜態資料成員的值對每個物件都是一樣,但它的值是可以更新的。只要對靜態資料成員的值更新一次,保證所有物件訪問更新後的相同的值,這樣可以提高時間效率。

應用格式

引用靜態資料成員時,採用如下格式:

《類名》::《靜態成員名》
如果靜態資料成員的訪問許可權允許的話(即public的成員),可在程式中,按上述格式來引用靜態資料成員。

注意事項

⑴類的靜態成員函式是屬於整個類而非類的物件,所以它沒有this指標,這就導致了它僅能訪問類的靜態資料和靜態成員函式。

⑵不能將靜態成員函式定義為虛函式。

⑶由於靜態成員宣告於類中,操作於其外,所以對其取位址操作,就多少有些特殊,變數位址是指向其資料型別的指標 ,函式位址型別是乙個「nonmember函式指標」。

⑷由於靜態成員函式沒有this指標,所以就差不多等同於nonmember函式,結果就產生了乙個意想不到的好處:成為乙個callback函式,使得我們得以將c++和c-based x window系統結合,同時也成功的應用於執行緒函式身上。

⑸static並沒有增加程式的時空開銷,相反她還縮短了子類對父類靜態成員的訪問時間,節省了子類的記憶體空間。

⑹靜態資料成員在<;定義或說明》;時前面加關鍵字static。

⑺靜態資料成員是靜態儲存的,所以必須對它進行初始化。

⑻靜態成員初始化與一般資料成員初始化不同:

初始化在類體外進行,而前面不加static,以免與一般靜態變數或物件相混淆;

初始化時不加該成員的訪問許可權控制符private,public等;

初始化時使用作用域運算子來標明它所屬類;

所以我們得出靜態資料成員初始化的格式:

<;資料型別》<;類名》::<;靜態資料成員名》=<;值》

⑼為了防止父類的影響,可以在子類定義乙個與父類相同的靜態變數,以遮蔽父類的影響。這裡有一點需要注意:我們說靜態成員為父類和子類共享,但我們有重複定義了靜態成員,這會不會引起錯誤呢?不會,我們的編譯器採用了一種絕妙的手法:name-mangling 用以生成唯一的標誌。在各通訊公司的筆試面試中經常出現的考題就是static的作用及功能。

在c和c++中,有三種使用儲存區的基本方式:

1)靜態儲存區(static memory)

在靜態儲存區中,聯結器(linker)根據程式的需求為物件分配空間。全域性變數、靜態類成員以及函式中的靜態變數都被分配在該區域中。乙個在該區域中分配的物件只被構造一次,其生存期一直維持到程式結束。在程式執行的時候其中的位址是固定不變的。在使用執行緒(thread,共享位址空間的併發物)的程式裡,靜態物件可能會引起一些問題,因為這時的靜態物件是被共享的,要對其正常訪問就需要進行鎖定操作。

2)自動儲存區(automatic memory)

函式的引數和區域性變數被分配在此。對同乙個函式或區塊的每一處呼叫,其在該區域內都有自己單獨的位置。這種儲存被自動建立和銷毀;因而才叫做「自動儲存區」。自動儲存區也被稱為是「在棧上的(be on the stack)」。

3)自由儲存區(free store)

在該區域中,程式必須明確的為物件申請空間,並可以在使用完畢之後釋放申請到的空間(使用new和delete運算子)。當程式需要其中更多的空間時,就使用new向作業系統提出申請。通常情況下,自由儲存區(也被稱作動態儲存區或者堆(heap))在乙個程式的生存期內是不斷增大的,因為其間被其它程式占用的空間從來都不被歸還給作業系統。

堆和棧分別是記憶體區域的一種劃分!

一般分成5個區,分別是堆,棧,自由儲存區,全域性/靜態區和常量儲存區!

棧-----就是那些由編譯器在需要的時候分配,在不需要的時候自動清楚的變數的儲存區。裡面的變數通常是區域性變數、函式引數等。

堆-----就是那些由new分配的記憶體塊,他們的釋放編譯器不去管,由我們的應用程式去控制,一般乙個new就要對應乙個delete。如果程式設計師沒有釋放掉,那麼在程式結束後,作業系統會自動**。

自由儲存區-----就是那些由malloc等分配的記憶體塊,他和堆是十分相似的,不過它是用free來結束自己的生命的。

全域性/靜態儲存區-----全域性變數和靜態變數被分配到同一塊記憶體中,在以前的c語言中,全域性變數又分為初始化的和未初始化的,在c++裡面沒有這個區分了,他們共同占用同一塊記憶體區。

常量儲存區-----這是一塊比較特殊的儲存區,他們裡面存放的是常量,不允許修改

參考:

堆,棧,靜態儲存區和常量儲存區

在c 中,記憶體分成4個區,他們分別是堆,棧,靜態儲存區和常量儲存區 1 棧,就是那些由編譯器在需要的時候分配,在不需要的時候自動清除的變數的存 儲區.裡面的變數通常是區域性變數,函式引數等.2 堆,又叫自由儲存區,它是在程式執行的過程中動態分配的,它最大的特性就是動.態性.由new分配的記憶體塊,...

堆 棧 自由儲存區 全域性 靜態儲存區和常量儲存區

在c 中,記憶體分成5個區,他們分別是堆 棧 自由儲存區 全域性 靜態儲存區和常量儲存區 1.棧由編譯器在需要的時候分配,在不需要的時候自動清楚的變數的儲存區。裡面的變數通常是區域性變數 函式引數等。棧空間初始化的時候,空間大小就確定了,棧指標指向棧頂 高位址 壓入棧時 棧指標減減,想低位址移動。棧...

堆 棧 自由儲存區 全域性 靜態儲存區和常量儲存區

堆 棧 自由儲存區 全域性 靜態儲存區和常量儲存區 在c 中,記憶體分成5個區,他們分別是堆 棧 自由儲存區 全域性 靜態儲存區和常量儲存區。棧,就是那些由編譯器在需要的時候分配,在不需要的時候自動清楚的變數的儲存區。裡面的變數通常是區域性變數 函式引數等。堆,就是那些由new分配的記憶體塊,他們的...