C++中static關鍵字

bian_qing_quan11發表於2017-07-30

首先說一下之前對static的認識吧。

之前就知道static是靜態的關鍵字,可以作用於變數、函式、類成員。並且static修飾的變臉為去全域性資料區。

最近為了複習,準備校招又對static進行了複習,上網查了些資料。經過一段的思考後又有不少的收穫,所以還是要不斷的學習呀。下面就接下網上搜到的,說一說static的用法的。


首先我們要有一個這個瞭解,static變數位於全域性資料區(全域性變臉也在全域性資料區),也就是說static變數的“生命週期”是整個程式,但是static變數的訪問許可權沒有發生改變。

1、static區域性變數 VS 普通區域性變數

在函式內部的static區域性變數在函式被第一次呼叫時初始化一次,下次在呼叫這個函式時不會重新為變數分配記憶體進行初始化,仍然使用的上一次建立的變數。出了函式作用域,static區域性變數沒有被銷燬(因為它在全域性資料區)。但是不能在函式作用域之外訪問(因為它是一個區域性變數)。

普通的區域性變數是存放在棧區的,過了作用域就會被銷燬掉。

程式碼:

#include<iostream>
#include<string>
using namespace std;

void foo(int b)
{
	static int a = 3;
	cout << "a = " << a << "; b = " << b;
	a += b;
	cout << "; a += b後:" << a << endl;
}
int main()
{
	foo(2);//第一次呼叫foo
	foo(1);//第二次呼叫foo,使用上一次建立的變數a
	return 0;
}
結果:


通過結果我們可以看出來第一次呼叫foo時,為區域性static變數a
申請記憶體,並初始化為3,然後執行a+=2,後a=5;第二次呼叫foo時,之前a的記憶體沒有銷燬掉(因為a存放在全域性資料區),執行了a+=1後變為6.

那麼我們總結一下,靜態區域性變數的特點(括號內為note:2,也就是區域性變數的對比):
(1)該變數在全域性資料區分配記憶體(區域性變數在棧區分配記憶體);
(2)靜態區域性變數在程式執行到該物件的宣告處時被首次初始化,即以後的函式呼叫不再進行初始化(區域性變數每次函式呼叫都會被初始化);
(3)靜態區域性變數一般在宣告處初始化,如果沒有顯式初始化,會被程式自動初始化為0(區域性變數不會被初始化);
(4)它始終駐留在全域性資料區,直到程式執行結束。但其作用域為區域性作用域,也就是不能在函式體外面使用它(區域性變數在棧區,在函式結束後立即釋放記憶體);

2、在某個檔案中的static全域性變數 VS 普通全域性變數

在檔案開始的地方定義的變數為全域性變數,全域性static變數。

static int i = 1;  //全域性static變數
int j = 1;  //全域性變數
全域性變數和全域性static變數的區別在於,全域性static不能跨檔案使用,而全域性變數可以跨檔案使用。

case1如下,在a.c檔案中有一個全域性變數,在檔案b.c中使用extern關鍵字就可以使用這個全域性變數了。

//檔案 a.c  中
int n = 15;  //全域性變數
  
//檔案 b.c中  
#include <stdio.h>  
  
extern int n;  
 
void fn()  
{  
    n++;  
    printf("after: %d\n",n);  
}  
  
  
void main()  
{  
    printf("before: %d\n",n);  
    fn();  
}  
輸出為:before: 15
                  after: 16


case2:在檔案a.c中有一個全域性static變數,在檔案b.c中使用extern關鍵字,但仍然不能使用這個全域性static變數。

//檔案 a.c  
static int n = 15;  //全域性static變數
  
//檔案 b.c  
#include <stdio.h>  
  
extern int n;  
  
void fn()  
{  
    n++;  
    printf("after: %d\n",n);  
}  
  
void main()  
{  
    printf("before: %d\n",n);  
    fn();  
} 
此時,會出現undeference to "n"的錯誤。

全域性static使用extern跨檔案使用。


3、某個檔案內的static函式 VS 普通函式

這個類似於全域性變數和全域性static變數。static函式不能跨檔案使用。

檔案a.c中的static函式,不能使用extern在b.c檔案中使用;

a.c中的普通函式,可以使用extern在b.c中使用;


4、static成員變數 VS 普通成員變數

類中的static成員變數不屬於類的某個特定的instance,而是出於整個class,被類的所有物件共享。無論建立多少個物件,在記憶體中只有一份(位於全域性資料區)。

而類的普通成員變數是屬於某個instance的,建立多少個物件,就會有多少個記憶體來存放這個變數(位於棧上)。普通成員變數,屬於某個instance。

類名::變數名;


5、static成員函式 VS static普通函式

static成員函式與static成員變數類似,屬於類,而不會屬於類的某一個特定例項。static成員函式沒有this指標。

普通成員函式,在函式形參的第一個位置隱藏了一個&obj,相當於是將這個函式與obj物件繫結在一起,this指標。普通成員函式屬於類的某一個例項。

靜態成員函式有特點
1.靜態成員之間可以相互訪問,包括靜態成員函式訪問靜態資料成員和訪問靜態成員函式;
2.非靜態成員函式可以任意地訪問靜態成員函式和靜態資料成員;
3.靜態成員函式不能訪問非靜態成員函式和非靜態資料成員;
4.呼叫靜態成員函式,可以用成員訪問操作符(.)和(->)為一個類的物件或指向類物件的指標呼叫靜態成員函式,也可以用類名::函式名呼叫(因為他本來就是屬於類的,用類名呼叫很正常)

類名::函式名(實參);


相關文章