1. 程式人生 > >C/C++:static用法總結

C/C++:static用法總結

.sh pre 值類型 定義和使用 靜態 public out pan -1

前言:static是C/C++中一個很重要的關鍵字,最近閱讀了很多博客和資料,遂在此對自己的學習筆記進行簡單的總結並發表在這裏

一、C語言中的static

? 靜態全局變量:在全局變量之前加上關鍵字static,該全局變量就被定義成了一個靜態全局變量

特別註意:

1.靜態全局變量在內存中的存儲位置:靜態區(全局區)。 [註]:靜態區(全局區)在整個程序運行期間都存在

2.靜態全局變量的初始化:未經初始化的靜態全局變量會被程序自動初始化為0。 [註]:在C語言中,未經初始化的全局變量的值是任意的;而在C++中,未經初始化的全局變量也會被程序自動初始化為0

3.全局變量和靜態全局變量的存儲方式是一樣的

,但不同的是全局變量在整個源代碼中都是可以使用的,而靜態全局變量只能在當前文件中使用。比如一個程序有3個文件a.cpp、b.cpp和c.cpp,如果在文件a.cpp中定義了一個全局變量x,那麽變量x在文件a.cpp、b.cpp和c.cpp中都可以使用;但如果在文件a.cpp中定義了一個靜態全局變量y,那麽變量y只能在文件a.cpp中使用文件b.cpp和文件c.cpp都不可以使用該靜態全局變量y

源文件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用法總結