C/C++:static用法總結
前言:static是C/C++中一個很重要的關鍵字,最近閱讀了很多博客和資料,遂在此對自己的學習筆記進行簡單的總結並發表在這裏
一、C語言中的static
? 靜態全局變量:在全局變量之前加上關鍵字static,該全局變量就被定義成了一個靜態全局變量
特別註意:
1.靜態全局變量在內存中的存儲位置:靜態區(全局區)。 [註]:靜態區(全局區)在整個程序運行期間都存在
2.靜態全局變量的初始化:未經初始化的靜態全局變量會被程序自動初始化為0。 [註]:在C語言中,未經初始化的全局變量的值是任意的;而在C++中,未經初始化的全局變量也會被程序自動初始化為0
3.全局變量和靜態全局變量的存儲方式是一樣的
源文件file1.cpp:
1 // 文件file1.cpp 2 int value1=10;//全局變量value1 3 static int value2;//靜態全局變量value2,默認初始化為0 4 ......
源文件file2.cpp:
1 // 文件file2.cpp 2 extern int value1; //成功:期望使用文件file1中定義的全局變量value1 3 extern int value2; //錯誤:期望使用文件file1中定義的靜態全局變量value2,但value2是static類型,只能在file1中使用,無法被其他文件使用 4 ......
4.使用靜態全局變量的好處:
a.將一個全局變量定義為靜態全局變量,相當於讓該全局變量對該程序的其他源文件進行了“隱藏”,也就是說該靜態全局變量只能在定義它的源文件中使用,而程序的其他源文件則無法訪問該變量
b.程序中的其他源文件中可以使用與該靜態全局變量同名的變量,而不會發生沖突
5.在C/C++程序中,如果一個全局變量僅僅在單個源文件中使用,則可以將該全局變量修改為靜態全局變量,以降低模塊間的耦合度
? 靜態局部變量:在局部變量之前加上關鍵字static,該局部變量就被定義成了一個靜態局部變量
特別註意:
1.靜態局部變量在內存中的存儲位置:靜態區(全局區)。[註]:普通局部變量在內存中的存儲位置為棧區
2.靜態局部變量的初始化:未經初始化的靜態局部變量會被程序自動初始化為0。[註]:在C/C++中,未經初始化的普通局部變量值是任意的
3.static並沒有改變局部變量的作用域。換句話說就是靜態局部變量的作用域仍是局部作用域,當定義它的函數或語句塊結束的時候,其作用域也就隨之結束。 [註]:與之相反,static改變了全局變量的作用域(在聲明它的文件之外是不可見的)
4.static雖然沒有改變局部變量的作用域,但它改變了局部變量在內存中的存儲位置(而static修飾的全局變量在內存中的存儲位置則沒有被static改變),即從原來的棧區中存放改變為靜態區(全局區)中存放。因此靜態局部變量在離開其作用域時,並沒有像一般局部變量那樣被銷毀,而是仍駐留在內存中的靜態區(全局區)中,直到程序結束,只不過在其離開自己的作用域時,我們無法再對其進行訪問。
1 #include<iostream> 2 using namespace std; 3 int count=1; 4 int fun(){ 5 static int count=10; 6 return count--; 7 } 8 int main(){ 9 cout<<"Global\tLocal Static"<<endl; 10 for(int i=1;i<=10;i++){ 11 cout<<" "<<count++<<"\t "<<fun()<<endl; 12 } 13 return 0; 14 }
5.在C/C++中,如果全局變量僅有單個函數訪問,則可以將該全局變量改為該函數的靜態局部變量,以降低模塊間的耦合度
? 靜態函數:在函數的返回值類型前加上關鍵字static,該函數就被定義成了一個靜態函數
特別註意:
1.和靜態全局變量相似,靜態函數只能在聲明它的源文件中可見,而不能被該程序的其他源文件所使用。
源文件file1.cpp:
1 //文件file1.cpp 2 ...... 3 extern void fun1(){......} //定義函數fun1 4 static void fun2(){......} //定義靜態函數fun2 5 ......
源文件file2.cpp:
1 //文件file2.cpp 2 ...... 3 extern void fun1();//成功:期望使用文件file1.cpp中的函數fun1 4 extern void fun2();//錯誤:期望使用文件file1.cpp中的靜態函數fun2,但fun2是static類型函數,只能在file1中使用,無法被其他文件使用
2.使用靜態函數的好處:
a.在該程序的其他源文件中可以定義和使用與該靜態函數同名的函數,而不會發生沖突
b.將一個普通函數定義為函數,相當於讓該函數對該程序的其他源文件進行了“隱藏”,也就是說該靜態函數只能在定義它的源文件中使用,而程序的其他源文件則無法調用該函數。
c.靜態函數會被自動分配在一個一直使用的存儲區域,直到程序結束。這樣避免了普通函數在調用時的進棧出棧操作,從而提高程序的運行速度
? 總結:static在C語言中的作用:
——隱藏功能:static修飾的全局變量和普通函數只能在定義它們的源文件中使用,相當於對程序中的其他源文件進行了隱藏
——默認初始化功能:static修飾的變量,不管是全局變量還是局部變量,在用戶沒有顯式初始化它們的條件下,系統都會將他們默認初始化為0
——延長“壽命”功能:static修飾的局部變量存儲在內存的靜態區(全局區)而非棧區,而靜態區中存儲的內容只會在程序結束時被OS釋放,因此當static修飾的局部變量離開自己的作用域時,其不會像一般局部變量那樣被系統銷毀,而是一直駐留在系統的內存中,直到程序結束。
二、C++中的static
? 靜態數據成員:自定義類中被static修飾的成員變量
特別註意:
1.靜態數據成員在內存中的存儲位置:靜態區(全局區)
2.使用:
語法:類名::靜態數據成員名
3.靜態數據成員屬於類。換句話說就是類的靜態數據成員為其所有對象所共享,不管該類有多少對象,靜態數據成員只有一份存儲於公共的內存中
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 class Student{ 5 public: 6 static int count;//記錄該類的對象的個數 7 Student(){ 8 count++; 9 } 10 Student(string name,int age):Name(name),Age(age){ 11 count++; 12 } 13 ~Student(){ 14 count--; 15 } 16 private: 17 string Name; 18 int Age; 19 }; 20 int Student::count=0; //對count進行初始化 21 int main(){ 22 Student stu1("Tomwenxing",23); 23 Student stu2("Ellen",22); 24 Student stu3("Jack",24); 25 cout<<"Student類的對象的個數:"<<Student::count<<endl; 26 return 0; 27 }
? 靜態成員函數:自定義類中被static修飾的成員函數
特別註意:
1.在C++的自定義類中,一個常規的成員函數聲明往往意味著:
? 該成員函數能夠訪問其所在類的私有部分
? 該成員函數位於其所在類的作用域之中
? 該成員函數必須由一個對象去激活從而被調用(通過this指針來實現)
如果將該類的一個成員函數聲明為static,則可以只讓它擁有前兩種性質
2.使用:
語法1:類名::靜態成員函數名
語法2:對象名.靜態成員函數名
3.和靜態數據成員一樣,靜態成員函數也屬於類,即類的靜態成員函數為其所有對象所共享。
4.類中的普通成員函數既可以訪問一般成員變量,也可以訪問靜態數據成員;而類中的靜態成員函數只能訪問類中的靜態數據成員。
[解釋]:編譯器在編譯程序中的自定義類時,會在類中的每個普通成員函數中插入this指針,而對static修飾的靜態成員函數則不會插入this指針。由於靜態成員函數中沒有this指針,因此靜態成員函數無法在其函數體內訪問非靜態數據成員;相反,由於靜態數據成員屬於類而非特定對象,故不需要this指針也可以在函數體內訪問靜態數據成員,因此不管是普通成員函數還是靜態成員函數,都可以在其函數體內訪問靜態數據成員。
5.同理,普通成員函數中可以調用靜態成員方法,而靜態成員方法中不能調用普通成員函數
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 class Student{ 5 public: 6 static int count; //靜態數據成員 7 Student(){ 8 count++; 9 } 10 Student(string name,int age):Name(name),Age(age){ 11 count++; 12 } 13 ~Student(){ 14 count--; 15 } 16 void show1(); 17 static void show2(); 18 private: 19 string Name; 20 int Age; 21 22 }; 23 int Student::count=0; //對count進行初始化 24 /* 25 編譯器對成員函數show1的改寫: 26 void Student::show1(Student* const this){ 27 cout<<"Name:"<<this->Name<<endl; 28 cout<<"Age:"<<this->Age<<endl; 29 cout<<"Count:"<<count<<endl; 30 show2(); 31 */ 32 void Student::show1(){ 33 cout<<"調用了方法show1"<<endl; 34 cout<<"Name:"<<Name<<endl; 35 cout<<"Age:"<<Age<<endl; 36 cout<<"Count:"<<count<<endl; 37 show2();//在普通成員函數中調用靜態成員函數 38 } 39 void Student::show2(){ //編譯器不會為靜態成員函數添加this指針 40 cout<<"調用了方法show2"<<endl; 41 //cout<<"Name:"<<Name<<endl; //錯誤:靜態成員函數不能訪問非靜態數據成員 42 //cout<<"Age:"<<Age<<endl; //錯誤:靜態成員函數不能訪問非靜態數據成員 43 //show1(); //錯誤:靜態成員函數中不能調用普通成員函數 (只能以this->show1()的形式調用) 44 cout<<"Count:"<<count<<endl; 45 } 46 int main(){ 47 Student stu1("Tomwenxing",23); 48 Student stu2("Ellen",22); 49 Student stu3("Jack",24); 50 stu3.show1(); 51 cout<<"----------分界線----------------"<<endl; 52 stu2.show2();//可以通過對象來調用靜態成員函數 53 cout<<"----------分界線----------------"<<endl; 54 Student::show2() ;//也可以通過類來調用靜態成員函數 55 return 0; 56 }
C/C++:static用法總結