日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

C/C++中的static關鍵字詳解_C 語言

作者:-YIN ? 更新時間: 2022-05-24 編程語言

static是 C/C++中的關鍵字之一,是常見的函數與變量(C++中還包括類)的修飾符,它常被用來控制變量的存儲方式和作用范圍。 在眾多高級語言中都有其作為關鍵字或函數出現,所以這也是應當被程序員熟知其各種含義的一個單詞

在這里插入圖片描述

我們知道在函數內部定義的變量,當程序執行到它的定義處時,編譯器為它在棧上分配空間,函數在棧上分配的空間在此函數執行結束時會釋放掉,這樣就產生了一個問題: 如果想將函數中此變量的值保存至下一次調用時,如何實現? 最容易想到的方法是定義為全局的變量,但定義一個全局變量有許多缺點,最明顯的缺點是破壞了此變量的訪問范圍(使得在此函數中定義的變量,不僅僅只受此函數控制)。static 關鍵字則可以很好的解決這個問題。

另外,在 C++ 中,需要一個數據對象為整個類而非某個對象服務,同時又力求不破壞類的封裝性,即要求此成員隱藏在類的內部,對外不可見時,可將其定義為靜態數據。

在這里插入圖片描述

C/C++ 中的 static

這里 static 作用主要影響著變量或函數的生命周期作用域,以及存儲位置

1. 靜態局部變量

定義在函數內部的變量稱為局部變量(Local Variable),它的作用域僅限于函數內部, 離開該函數后就是無效的

當 static 修飾局部變量時:

  • 變量的存儲區域由變為靜態常量區
  • 變量的生命周期由局部變為全局
  • 變量的作用域不變。

函數調用開辟棧幀,函數中的局部變量在棧上分配存儲空間,當函數執行完畢,函數棧幀銷毀,棧空間由系統回收

而在static修飾函數局部變量的時,其修飾的靜態局部變量只執行初始化一次,延長了局部變量的生命周期,直到程序運行結束以后才釋放,但不改變作用域。

下面用代碼進行驗證:

#include 
 void fun()
{
	static int val = 0;   //static 修飾局部變量
	val++;
	printf("%d\n", val);
}
int main()
{
	for (int i = 0; i < 7; i++){
		fun();
	}
	return 0;
}

沒有?static?時, 函數每調用一次, 變量就會進行一次初始化值為 0,

當由?static修飾時, 初始化語句只會被執行一次所以值會一直累加。

在這里插入圖片描述

2. 靜態全局變量

在所有函數外部定義的變量稱為全局變量(Global Variable),它的作用域默認是整個程序,也就是所有的源文件,包括 .c 和 .h 文件。

當?static?修飾全局變量時:

  • 變量的存儲區域在全局數據區的靜態常量區
  • 變量的作用域由整個程序變為當前文件。(extern聲明也不行)
  • 變量的生命周期不變。

一個全局變量被?static?修飾,使全局變量只能在定義變量的當前文件使用,不能在其余文件使用,即使?extern外部聲明也不行。

原因: 屬于文件作用域的聲明在缺省的情況下為?external?鏈接屬性, 如定義個全局變量int g_a = 1;,?a的鏈接屬性為external,而加上?static會修改變量的缺省鏈接屬性,改為internal

聲明了全局變量 g_a 和 g_b (具有?external?鏈接屬性 )的其他源文件在使用這兩個變量時實際訪問的是生命與此處的這兩個變量;但是 g_c 只能由這個源文件訪問,因為鏈接屬性**為internal

int g_a = 1;
extern int g_b;
static int g_c;

代碼驗證:

// add.c
static int global_val = 27;   //static 修飾全局變量
 //staticdemo1.c
extern global_val;
 int main()
{
	printf("%d", global_val);
	return 0;
}

不用?static?修飾?global_val?時的結果

在這里插入圖片描述

而使用 static 修飾時,鏈接時就會出現鏈接錯誤無法執行。

在這里插入圖片描述

全局變量 與 extren

具有?extrenal?鏈接屬性的實體在其他語言術語中稱作全局實體(global entity ),所有源文件中的函數均可以訪問它。只要變量并非聲明與代碼塊或者函數定義內部,它在缺省的情況下鏈接屬性即為?extrenal。如果一個變量聲明與代碼塊內部,在它面前添加?extren?關鍵字將使它使它所引用的是全局變量而非局部變量。

具有鏈接屬性為?extrenal?的實體總是具有靜態存儲類型。 全局變量在程序開始執行前創建,并在整個執行過程中始終存在。從屬于函數的局部變量在函數在函數開始執行時進行創建,在函數執行完畢后銷毀,但用于執行函數的機器指令在程序生命周期內一直存在。

使用 extren 進行聲明提高代碼的可讀性是良好的編程習慣。

3. static 修飾函數

函數的作用域與全局變量一樣都是整個程序。

當 static 修飾函數時:

函數的作用域由整個程序變為當前文件。(extern聲明也不行)

一個函數被?static?修飾,使函數只能在定義的源文件使用,不能在其余文件使用,即使?extern外部聲明也不行。(同static?修飾全局變量)

如果我們將函數聲明為?static,就會把它的鏈接屬性從external,改為internal,這樣將使得其他源文件不能訪問這個函數;對于函數而言,存儲類型不是問題,因為代碼總是存儲在只讀的代碼區中。

// add.c
static int add(int a, int b)
{
	return a + b;
}
 //staticdemo1.c
extern add(int a, int b);
 int main()
{
	printf("%d", add(10, 20));
	return 0;
}

這里直接看結果:

沒有?static?修飾:

在這里插入圖片描述

被?static?修飾:報了與修飾全局變量時同樣的鏈接錯誤。

在這里插入圖片描述

C++的 static 成員

聲明為static類成員稱為類的靜態成員,用static修飾的成員變量,稱之為靜態成員變量;用static修飾的?成員函數,稱之為靜態成員函數

注:靜態的成員變量一定要在類外進行初始化

class A
{
public :
	A(){   //構造函數
		_count++;
	}
	A(const A& y){
		_count++;
	}
	static int GetCount(){    //靜態成員函數
		return _count;
	}
public:      
	int a;
	//靜態成員變量--》在類中的是聲明要在類外進行定義
	static int _count;  
};
};
 int A::_count = 0;   //靜態變量 _count 定義
 void TestA() {
	cout << A::GetCount() << endl;  // 類靜態成員通過 類名::靜態成員 來訪問
	A a1, a2; 
	A a3(a1);
	cout << A::GetCount() << endl;
}

靜態成員變量?

1.靜態成員變量必須在類外進行定義定義時不用加?static?,類中只是聲明

在這里插入圖片描述

2.靜態成員變量為所有類對象所共享,并沒有包含在具體的對象中。

所以并不影響?sizeof()?大小

3.靜態成員變量的訪問:?

  • 類名::靜態成員變量名?
  • 對象.靜態成員變量名。
cout << A::_count << endl;
cout << a1._count << endl;

在這里插入圖片描述

類的對象可以使用靜態成員函數和非靜態成員函數。

注:靜態成員變量也受訪問限定符(public、protected、private)的限制。 所以私有的仍要通過類成員函數接口來進行訪問,可以在通過類中公有的成員函數進行訪問,

cout << A::GetCount() << endl;

但這種方式調用獲取靜態成員變量必須由靜態成員函數訪問,不能通過類名來調用類的非靜態成員函數,否則就會出錯

在這里插入圖片描述

靜態成員函數

1.靜態成員函數沒有隱藏的?this?指針,不能訪問非靜態成員(變量、 函數)!

在這里插入圖片描述

因為靜態成員函數沒有隱藏的?this?指針所以也不能定義成const成員函數(const 本質就是修飾隱藏參數this )

在這里插入圖片描述

2.靜態成員函數不能調用非靜態成員函數。

在這里插入圖片描述

3.非靜態成員函數可以調用靜態成員函數。

static void fun(){
		_count = 0;
	}
	int GetCount(){
		//cout << this << endl;    
		fun();
		return _count;
	}

總結:

(1) 靜態成員變量使用前必須先初始化(在類外定義),如:int A::_count = 0;

(2) 靜態成員變量為所有類對象所共享,也受訪問限定符(public、protected、private)的限制

(3)?靜態成員函不能調用非靜態成員函數,非靜態成員函數可以調用靜態成員函數

(4) 靜態成員函數沒有隱藏的?this?指針

原文鏈接:https://blog.csdn.net/weixin_45910068/article/details/123621193

相關推薦

欄目分類
最近更新