一、限制符號(hào)的作用域只在本程序文件
- 若變量或函數(shù)(統(tǒng)稱符號(hào))使用static修飾,則只能在本程序文件內(nèi)使用,其他程序文件不能調(diào)用(非static的可以通過(guò)extern 關(guān)鍵字聲明該變量是在其他文件內(nèi)定義的,此文件可調(diào)用)。不加static修飾的,則默認(rèn)是可以被其他程序文件調(diào)用的。
- 本程序文件內(nèi)的非static函數(shù)也可以隨意調(diào)用static的變量和函數(shù)。只是限制了外部程序文件的函數(shù)不能調(diào)用。
原理:默認(rèn)的變量和函數(shù)名(統(tǒng)一稱為符號(hào))在編譯成匯編代碼.s文件時(shí),會(huì)有
.globl func_name,.globl指示告訴匯編器,func_name這個(gè)符號(hào)要被鏈接器用到(匯編文件在經(jīng)過(guò)匯編器處理成二進(jìn)制的.o文件時(shí),符號(hào)會(huì)被變量或函數(shù)實(shí)際的地址值代替),所以要在目標(biāo)文件的符號(hào)表中標(biāo)記它是一個(gè)全局符號(hào)。如果一個(gè)符號(hào)沒(méi)有用.globl聲明,就表示這個(gè)符號(hào)不會(huì)被鏈接器用到。而static關(guān)鍵字修飾的符號(hào)在編譯成匯編代碼.s文件時(shí),就不會(huì)被.globl聲明,因此不會(huì)參與后序鏈接就不會(huì)被其他程序文件調(diào)用到。
(不同程序文件的函數(shù)變量互相調(diào)用是在鏈接各個(gè).o文件步驟后進(jìn)行的,前面預(yù)編譯、編譯、匯編步驟都是對(duì)單個(gè)程序文件進(jìn)行操作)
二、指定變量的存儲(chǔ)位置
- 對(duì)于函數(shù)內(nèi)的變量。auto變量(函數(shù)局部變量)都是在棧內(nèi)存區(qū)存放,函數(shù)結(jié)束后就自動(dòng)釋放。但是全局的和函數(shù)內(nèi)定義的static變量都是存放在數(shù)據(jù)區(qū)的,且只存一份,只在整個(gè)程序結(jié)束后才自動(dòng)釋放。
- 由于static變量只存一份即同一地址,所以不管函數(shù)調(diào)用多少次,函數(shù)內(nèi)定義static變量的語(yǔ)句只會(huì)在第一次調(diào)用時(shí)執(zhí)行,后面調(diào)用都不執(zhí)行也不再初始化,而是對(duì)該地址內(nèi)的數(shù)據(jù)進(jìn)行操作。
#include<iostream>
using namespace std;
void test()
{
static int a = 1;
a++;
cout << a << endl;
cout << &a << endl;
}
int main
{
test();
test();
test();
test();
}
輸出:
2
00C90008
3
00C90008
4
00C90008
5
00C90008
//可見地址只有一個(gè)
三、C++類的靜態(tài)成員變量
- 是屬于類,而不屬于某個(gè)實(shí)例對(duì)象,因此也只有一個(gè)地址保存一份數(shù)據(jù)存放于數(shù)據(jù)區(qū)。在類中只是聲明,并不是定義,因此不分配內(nèi)存,對(duì)類用sizeof求大小也不會(huì)將static變量得大小加入。
- 必須在類聲明的外部,以及main()函數(shù)的外部,也就是全部變量區(qū)域?qū)︻惖膕tatic成員變量再次定義(定以后才分配唯一內(nèi)存,此時(shí)該類靜態(tài)成員變量相當(dāng)于是全局的靜態(tài)變量了,只是調(diào)用的時(shí)候要使用類名加::)。若只定義不賦值初始化,則默認(rèn)初始化為0。
- public的靜態(tài)數(shù)據(jù)成員既可以通過(guò)類名引用,也可以通過(guò)對(duì)象名引用(會(huì)自動(dòng)轉(zhuǎn)換成類名引用)。
四、C++類的靜態(tài)成員函數(shù)
- 只能調(diào)用本類的靜態(tài)成員變量或函數(shù),不能調(diào)用本類的非靜態(tài)成員函數(shù)和變量。因?yàn)榉庆o態(tài)成員函數(shù)和變量在類成員函數(shù)中調(diào)用時(shí),都是由形參中隱含一個(gè)指向當(dāng)前實(shí)例對(duì)象的this指針來(lái)調(diào)用。然而靜態(tài)成員函數(shù)沒(méi)有這個(gè)this形參。
#include<iostream>
using namespace std;
class A
{
private:
int a;
static int sa;
public:
void show()
{
cout << sa++ << endl;
}
static void s_show()
{
//cout << a << endl; //報(bào)錯(cuò),靜態(tài)成員函數(shù)不能調(diào)用非靜態(tài)成員變量。無(wú)法使用this.a
cout << sa << endl;
//show(); //報(bào)錯(cuò),靜態(tài)成員函數(shù)不能調(diào)用非靜態(tài)成員函數(shù)。無(wú)法使用this.show()
}
};
int A::sa = 1; //只在定義時(shí)可以不受private的限制,可以用類名調(diào)用私有成員。其他時(shí)候不行
//若不賦初值,則默認(rèn)初始化賦值0
int main()
{
cout << sizeof(A) << endl; //輸出結(jié)果為4,并不是8,因?yàn)閟tatic成員變量不占用類的大小,
//在類中只是聲明,而在類外定義并分配內(nèi)存
//cout << A::sa << endl; //sa是private私有成員,不能用類名來(lái)訪問(wèn)
A ca;
ca.show();
A::s_show();
}
輸出:
4
1
2