1. 程式人生 > >[C/C++]_[初級]_[關於static修飾符的說明]

[C/C++]_[初級]_[關於static修飾符的說明]

場景:

1. static 修飾具有靜態共享特性, 在C/C++裡一般用來作為共享變數使用,或者節約記憶體宣告的常量或不改變大小的儲存區.

2. static活用的話也可以作為單例模式的便捷方式.

3. 總的說來static是檔案範圍內可見的,或類,函式範圍內可見的. 注意: 非全域性可見的.

4. 注意, 檔案範圍內可見的static(一種是檔案內宣告的靜態變數,一種是類靜態成員變數)會在main執行前先執行, 如果是類, 那麼會呼叫建構函式, 如果是原始型別, 會初始化為0.

下邊是對static關鍵字的詳細說明,參考:

static 關鍵字可用於在全域性範圍、名稱空間範圍和類範圍宣告變數和函式。 靜態變數還可在本地範圍宣告。

靜態持續時間意味著,在程式啟動時分配物件或變數,並在程式結束時釋放物件或變數。 外部連結意味著,變數的名稱在用於宣告變數的檔案的外部是可見的。 相反,內部連結意味著,名稱在用於宣告變數的檔案的外部是不可見的。 預設情況下,在全域性名稱空間中定義的物件或變數具有靜態持續時間和外部連結。 在以下情況下,可使用 static 關鍵字。

在檔案範圍(全域性和/或名稱空間範圍)內宣告變數或函式時,static 關鍵字將指定變數或函式具有內部連結。 在宣告變數時,變數具有靜態持續時間,並且除非您指定另一個值,否則編譯器會將變數初始化為 0。

在函式中宣告變數時,static 關鍵字將指定變數將在對該函式的呼叫中保持其狀態。

在類宣告中宣告資料成員時,static 關鍵字將指定類的所有例項共享該成員的一個副本。 必須在檔案範圍內定義靜態資料成員。 宣告為 conststatic 的整型資料成員可以有初始值設定項。

在類宣告中宣告成員函式時,static 關鍵字將指定類的所有例項共享該函式。 由於函式沒有隱式 this 指標,因此靜態成員函式不能訪問例項成員。 若要訪問例項成員,請使用作為例項指標或引用的引數來宣告函式。

不能將聯合成員宣告為靜態的。 但是,全域性宣告的匿名聯合必須是顯式宣告的 static。
從 C++11 開始,可以保證靜態本地變數初始化是執行緒安全的。 此功能有時稱為神奇的靜態物件。 但是,在多執行緒應用程式中,必須同步所有後續分配。 可以通過使用 /Zc:threadSafeInit- 標誌避免對 CRT 形成依賴,來禁用執行緒安全的靜態物件功能。

test.cpp
#include <iostream>
#include <stdlib.h>
#include <vector>

// 5.全域性宣告的匿名聯合必須是顯式宣告的 static。g++貌似不用顯示static
union
{
	int i;
	char j[4];
	int k;
}tt;

class A
{
public:
	A(int i)
	{
		std::cout << "A:" << i << " Object Count: " << ++count_ << std::endl;
	}
	~A(){}

	// 3.在類宣告中宣告資料成員時,static 關鍵字將指定類的所有例項共享該成員的一個副本。 
	static int count_;

	// 3.宣告為 conststatic 的整型資料成員可以有初始值設定項
	static const int index_ = 0;

	// 在類宣告中宣告成員函式時,static 關鍵字將指定類的所有例項共享該函式。 
	// 由於函式沒有隱式 this 指標,因此靜態成員函式不能訪問例項成員。 
	// 若要訪問例項成員,請使用作為例項指標或引用的引數來宣告函式。
	static void Log(A* a1,A& a2)
	{
		a1->Print();
		a2.Print();
	}

	void Print()
	{
		// 2.在函式中宣告變數時,static 關鍵字將指定變數將在對該函式的呼叫中保持其狀態。
		static int i  = 0;
		std::cout << "i: " << ++i << std::endl;
	}

	union YY
	{
		//static int i; 錯誤. 5.不能將聯合成員宣告為靜態的
		int i;
		char j[4];
		int k;
	}yy;

};

// 3.必須在檔案範圍內定義靜態資料成員。根據條款1,初始化為0.
int A::count_;

// 1.在檔案範圍(全域性和/或名稱空間範圍)內宣告變數或函式時,static 關鍵字將指定變數或函式具有內部連結。 
// 在宣告變數時,變數具有靜態持續時間,並且除非您指定另一個值,否則編譯器會將變數初始化為 0。
static A a1(1);
// 初始化為0.
static int gNum;

// 非static,具有靜態持續時間和外部連結特性.
A a2(2);


int main(int argc, char const *argv[])
{
	std::cout << "begin main" << std::endl;
	// 使用C++11特性的auto自動轉換型別.
	auto arr = new std::vector<int>();

	a1.Print();
	a2.Print();

	A::Log(&a1,a2);
	//int integer = A::ut.i;
	std::cout << "tt.i: " << tt.i << std::endl;
	std::cout << "a1::yy.i: " << a1.yy.i << std::endl;
	std::cout << "end main" << std::endl; 
	return 0;
}

輸出:
A:1 Object Count: 1
A:2 Object Count: 2
begin main
i: 1
i: 2
i: 3
i: 4
tt.i: 0
a1::yy.i: 0
end main