亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

解析static!

2019-11-17 05:13:54
字體:
來源:轉載
供稿:網友

[size=18:7291e6e16b][color=darkblue:7291e6e16b][b:7291e6e16b]解析static![/b:7291e6e16b][/color:7291e6e16b][/size:7291e6e16b]
http://asp.6to23.com/vcPRogram/articlemanage/article/jxstatic.asp?title=解析static&index=58

通常理解static只是指靜態存儲的概念,事實上在c++里面static包含了兩方面的含義。
1)在固定地址上的分配,這意味著對象是在一個非凡的靜態區域上創建的,而不是每次函數調用的時候在堆棧上動態創建的,這是static的靜態存儲的概念。
2) 另一方面,static能夠控制對象對于連接器的可見性。一個static對象,對于特定的編譯單元來說總是本地范圍的,這個范圍包括本地文件或者本地的某一個類,超過這個范圍的文件或者類是不可以看到static對象的,這同時也描述了連接的概念,它決定連接器能夠看到哪些名字。

[b:7291e6e16b]一,關于靜態存儲[/b:7291e6e16b]
對于一個完整的程序,他們在內存中的分布情況如下圖:
[img:7291e6e16b]http://asp.6to23.com/vcprogram/articlemanage/image/static.jpg[/img:7291e6e16b]
一般程序的由malloc,realloc產生的動態數據存放在堆區,程序的局部數據即各個函數內部的數據存放在棧區,局部數據對象一般會隨著函數的退出而釋放空間,對于static數據即使是函數內部的對象則存放在全局數據區,全局數據區的數據并不會因為函數的退出就將空間釋放。

[b:38f65016cf]二,函數內部的靜態變量[/b:38f65016cf]

通常,在函數體內定義一個變量的時候,編譯器使得每次函數調用時候堆棧的指針向下移動一個合適的位置,為這些內部變量分配內存。假如這個變量是一個初始化表達式,那么每當程序運行到這兒的時候程序都需要對表達式進行初始化。這種情況下變量的值在兩次調用之間則不能進行保存。

有的時候我們卻需要在兩次調用之間對變量的值進行保存,通常的想法是定義一個全局變量來實現。但這樣一來,變量已經不再屬于函數本身了,不再僅受函數的控制。因此我們有必要將變量聲明為static對象,這樣對象將保存在靜態存儲區域,而不是保存在堆棧中。對象的初始化僅僅在函數第一個被調用的時候進行初始化,每次的值保持到下一次調用,直到新的值覆蓋它。下面的例子解釋了這一點。
[code:1:38f65016cf]//****************************************
// 1.cpp
//****************************************
1 #include <iostream.h>
2 void add_n(void);
3 void main(){
4 int n=0;
5 add_n();
6 add_n();
7 add_n();
8 }
9 void add_n(void){
10 staticn=50;
11 cout<<”n=”<<n<<endl;
12 n++;
13 }[/code:1:38f65016cf]
程序運行結果為
[code:1:38f65016cf]n=50
n=51
n=52;[/code:1:38f65016cf]

HopeCao 回復于:2003-06-18 14:32:41
從上面的運行結果可以看出static n確實是在每次調用中都保持了上一次的值。假如預定義的靜態變量沒有提供一個初始值的話,編譯器會確保在初始化的時候將用零值為其初始化。static變量必須被初始化,但是零值初始化僅僅只對系統預定義類型有效,比如int,char,bool等等。事實上我們用到的不僅僅是這些預定義類型,大多數情況下可能用到結構,聯合或者類等各種用戶自定義的類型,對于這些類型用戶必須使用構造函數進行初始化。假如我們在定義一個靜態對象的時候沒有指定構造函數的參數,那就必須使用缺省的構造函數,假如缺省的構造函數也沒有的話則會出錯??聪旅娴睦?。
[code:1:30a24d7c00]//**************************************************
// 2.cpp
//**************************************************
1 #include <isotream.h>
2 class x{

3 int i;
4 public:
5 x(int i=0):i(i){
6 cout<<”i=”<<i<<endl;
7 }//缺省構造函數
8 ~x(){cout<<”x::~x()”<<endl;
9 };
10 void fn(){
11 staticx x1(47);
12 staticx x2;
13 }
14 main(){
15 fn();
16 }[/code:1:30a24d7c00]
程序運行結果如下
[code:1:30a24d7c00]i=47
i=0
x::~x()
x::~x()
[/code:1:30a24d7c00]

HopeCao 回復于:2003-06-18 14:34:19
從上面的例子可以看出靜態的x對象既可以使用帶參數的構造函數進行初始化,象x1,也可以使用缺省的構造函數,象x2。程序控制第一次轉到對象的定義點時候,而且只有第一次的時候才需要執行構造函數。假如對象既沒有帶參數的構造函數又沒有缺省構造函數則程序將無法通過編譯。

[b:eaa8a56606]三,類中的靜態成員[/b:eaa8a56606]

static靜態存儲的概念可以進一步引用到類中來。c++中的每一個類的對象都是該類的成員的拷貝,一般情況下它們彼此之間沒有什么聯系,但有時候我們需要讓它們之間共享一些數據,我們可以通過全局變量來實現,但是這樣的結果是導致程序的不安全性,因為任何函數都可以對這個變量進行訪問和修改,而且輕易與項目中的其余的名字產生沖突,因此我們需要一種兩全其美的方法,既可以當成全局數據變量那樣存儲,又可以隱藏在類的內部,與類本身聯系起來,這樣只有類的對象才可以操縱這個變量,從而增加了變量的安全性。

這種變量我們稱之為類的靜態成員,靜態成員包括靜態數據成員和靜態成員函數。類的所有的靜態數據成員有著單一的存儲空間而不管類的對象由多少,這些對象共享這塊存儲區域。因此每一個類的對象的靜態成員發生改變都會對其余的對象產生影響。先看下面的例子。
[code:1:eaa8a56606]//**************************************
// student.cpp
//**************************************
1. #include <iostream.h>
2. #include <string.h>
3. class student{
4. public:
5. student(char* pname=”no name”){
6. cout<<”create one student”<endl;
7. strcpy(name,pname);
8. number++;
9. cout<<number<<endl;
10. }
11. ~student() {
12. cout<<”destrUCt one student”<<endl;
13. number--;
14. cout<<number<<endl;
15. }
16. static number(){
17. return number; }
18. protected:
19. char nme[40]

20. staticint number;
21. }
22. void fn(){
23. student s1;
24. student s2;
25. cout<<student::number<<endl;
26. }
27. main(){
28. fn();
29. cout<<student::number<<endl;
30. }[/code:1:eaa8a56606]

程序輸出結果如下:
[code:1:eaa8a56606]create one student
1
create one student
2
2
destruct one student
1
destruct one student
0
0[/code:1:eaa8a56606]
上面的程序代碼中我們使用了靜態數據成員和靜態函數成員,下面我們先闡述靜態數據成員。

HopeCao 回復于:2003-06-18 14:38:32
[b:5282547077]四,靜態數據成員[/b:5282547077]
在代碼中我們可以看出,number既不是對象s1也不是對象s2的一部分,它是屬于student這個類的。每一個 student對象都有name成員,但是number成員卻只有一個,所有的student對象共享使用這個成員。s1.number與 s2.number是等值的。在student的對象空間中沒有為number成員保留空間,它的空間分配不在student的構造函數里完成,空間回收也不再析構函數里面完成。因此與name成員不一樣,它不會隨著對象的產生或者消失而產生或消失。
由于靜態數據成員的空間分配在全局數據區,因此在程序一開始運行的時候就必須存在,所以靜態成員的空間的分配和初始化不可能在函數包括main主函數中完成,因為函數在程序中被調用的時候才為內部的對象分配空間。這樣,靜態成員的空間分配和初始化只能由下面的三種途徑。一是類的外部接口的頭文件,那里聲明了類定義。二是類定義的內部實現,那里有類成員函數的定義和具體實現。三是應用程序的main()函數前的全局數據聲明和定義處。由于靜態數據成員必須實際的分配空間,因此不可能在類定義頭文件中分配內存。另一方面也不能在頭文件中類聲明的外部定義,因為那會造成多個使用該類的源程序重復出現定義。靜態數據成員也不能在main()函數的全局數據聲明處定義。假如那樣的話每一個使用該類的程序都必須在程序的 main()函數的全局數據聲明處定義一下該類的靜態成員。這是不現實的。唯一的辦法就是將靜態數據成員的定義放在類的實現中。定義時候用類名引導,引用時包含頭文件即可。
例如[code:1:5282547077]class a{
staticint i;
public:
//
}
在類定義文件中 int a::i=1;[/code:1:5282547077]
[color=blue:5282547077]有兩點需要注重的是[/color:5282547077]
[color=blue:5282547077]1.靜態數據成員必須且只能定義一次,假如重復定義,連接器會報告錯誤。同時它們的初始化必須在定義的時候完成。對于預定義類型的靜態數據成員,假如沒有賦值則賦零值。對于用戶自定義類型必須通過構造函數賦值,假如沒有構造函數包括缺省構造函數,編譯無法通過。
2. 局部類中不答應出現靜態數據成員。因為靜態數據成員必須在程序運行時候就存在這導致程序無法為局部類中的靜態數據成員分配空間。下面的代碼是不答應的。[/color:5282547077]
[code:1:5282547077]void fn(){
class foo{
staticint i;//定義非法。
public:
// }
}[/code:1:5282547077]

HopeCao 回復于:2003-06-18 14:43:07
[b:4008a128d4]五,靜態函數成員[/b:4008a128d4]
與靜態數據成員一樣,我們也可以創建一個靜態成員函數,它為類的全部服務而不是為某一個類的具體對象服務。靜態函數成員與靜態成員一樣,都是類的內部實現,屬于類定義的一部分。程序student.cpp中的number()就是靜態成員函數,它的定義位置與一般成員函數相同。
普通的成員函數一般都隱含了一個this指針,this指針指向類的對象本身,因為普通成員函數總是具體的屬于某個類的具體對象的。通常情況下 this是缺省的。如函數add()實際上是寫成this.add().但是與普通函數相比,靜態成員函數由于不是與任何的對象相聯系因此它不具有 this指針,從這個意義上講,它無法訪問屬于具體類對象的非靜態數據成員,也無法訪問非靜態成員函數,它只能調用其余的靜態成員函數。如下面的代碼

[code:1:4008a128d4]1 class x {
2 int i;
3 staticint j;
4 public:
5 x(int i=0):i(i){
6 j=i
7 }//非靜態成員函數可以訪問靜態函數成員和靜態數據成員。
8 int val() const {return i;}
9 staticint incr(){
10 i++;//錯誤的代碼,因為i是非靜態成員,因此incr()作為靜態成員函數無
11     //法訪問它。
12 return ++j;
13 }
14 staticint fn(){
15 return incr();//合法的訪問,因為fn()和incr()作為靜態成員函數可以互相訪
16 //問。
17 }
18 };
19 int x::j=0;
20 main(){……}[/code:1:4008a128d4]

li2002 回復于:2003-06-18 14:44:15
好啊,以前不了解static,現在知道了,建議加入精華!

HopeCao 回復于:2003-06-18 14:49:34
[color=blue:17500aa702]根據上面的程序可以總結幾點:
1. 靜態成員之間可以相互的訪問包括靜態成員函數訪問靜態數據成員和訪問靜態成員函數。
2. 非靜態成員函數可以任意的訪問靜態成員函數和靜態數據成員。
3. 靜態成員函數不能訪問非靜態成員函數和非靜態數據成員。[/color:17500aa702]
由于沒有this指針的額外開銷,因此靜態成員函數與全局函數相比速度上會有少許的增長。

[b:17500aa702]六,理解控制連接[/b:17500aa702]
理解控制連接之前我們先了解一下外部存儲類型的概念。一般的在程序的規模很小的情況下我們用一個源程序既可以表達完整。但事實上稍微有價值的程序都不可能只用一個程序來表達的,而是分割成很多的小的模塊,每一個模塊完成特定的功能,構成一個源文件。所有的源文件共享一個main函數。在不同的源文件之間為了能夠相互進行數據或者函數的溝通,這時候通常聲明數據或者函數為extern,這樣用extern聲明的數據或者函數就是全局變量或者函數。默認情況下的函數的聲明總是extern的。在文件范圍內定義的全局數據和函數對程序中的所有的編譯單元來說都是可見的。這就是通常我們所說的外部連接。
但有時候我們可能想限制一個名字對象的可見性,想讓一個對象在本地文件范圍內是可見的,這樣這個文件中的所有的函數都可以利用這個對象,但是不想讓本地文件之外的其余文件看到或者訪問該對象,或者外部已經定義了一個全局對象,防止內部的名字對象與之沖突。
通過在全局變量的前面加上static,我們可以做到這一點。在文件的范圍內,一個被聲明為static的對象或者函數的名字對于編譯單元來說是局部變量,我們稱之為靜態全部變量。這些名字不使用默認情況下的外部連接,而是使用內部連接。從下面的例子可以看出static是如何控制連接的。
工程文件為first.prj由兩個源文件組成。
[code:1:17500aa702]exam1.cpp
exam2.cpp
//***************************************
// exam1.cpp
//***************************************
1 #include <iostream.h>
2 int n;
3 void print_n();
4 void main()
5 {
6 n=20;
7 cout<<n<<endl;
8 print_n();
9 }

//****************************************
// exam2.cpp
//****************************************
10 staticn;
11 staticvoid staticfn();
12 void print_n()
13 {
14 n++;

15 cout<<n<<endl;
16 staticfn();
17 }
18 void staticfn()
19 {
20 cout<<n++<<endl;
21 }[/code:1:17500aa702]
程序運行結果如下
[code:1:17500aa702]20
1
1[/code:1:17500aa702]
下面我們將對上面的程序進行少量的改造,在看看執行結果如何。
[color=darkred:17500aa702]改造一:[/color:17500aa702]
[code:1:17500aa702]將exam1.cpp的第二行int n改為extern int n,這就是告訴程序我在此處聲明了變量n,但是真正的定義過程在別的文件中,此處就是exam2.cpp。但事實上exam2.cpp中僅僅聲明了 static int n。我們看看運行結果。vc中會通過編譯,但是在進行連接時候會給出一個“變量n找不到”的錯誤。這說明 exam1.cpp無法共享exam2.cpp中的static int n變量。[/code:1:17500aa702]
[color=darkred:17500aa702]改造二:[/color:17500aa702]
[code:1:17500aa702]我們在exam1.cpp的第二行和第三行之間增加void staticfn();同時在第八行和第九行之間增加staticfn()的調用。再看執行結果。vc會產生一個找不到函數staticfn的錯誤。這說明exam1.cpp無法共享 exam2.cpp中的staticfn()。[/code:1:17500aa702]
[color=blue:17500aa702]從上面的結論可以看出下面幾點:[/color:17500aa702]
[code:1:17500aa702]1. static解決了名字的沖突問題。使得可以在源文件中建立并使用與其它源文件甚至全局變量一樣的名字而不會導致沖突的產生。這一點在很大的項目中是很有用處的。
2. 聲明為靜態的函數不能被其他的源文件所調用,因為它的名字只對本地文件可見,其余的文件無法獲取它的名字,因此不可能進行連接。
在文件作用域下聲明的inline函數默認情況下認為是static類型。在文件作用域下聲明的const的常量默認情況下也是static存儲類型的。[/code:1:17500aa702]

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲自拍欧美另类| 日韩av免费观影| 欧美成人手机在线| 日本19禁啪啪免费观看www| 成人伊人精品色xxxx视频| 中文字幕日韩欧美在线| 久久777国产线看观看精品| 国产精品电影久久久久电影网| 国产精品www色诱视频| 欧美国产亚洲精品久久久8v| 国产69久久精品成人| 92看片淫黄大片看国产片| 91中文字幕一区| 91成人福利在线| 国产欧美中文字幕| 超碰日本道色综合久久综合| 欧美日韩不卡合集视频| 亚洲新声在线观看| 成人国产在线激情| 亚洲精品一二区| 久久久久久九九九| 亚洲精品视频播放| 色偷偷av一区二区三区乱| 欧美日韩免费区域视频在线观看| 欧美激情高清视频| 久久久视频精品| 国产亚洲精品美女久久久| 亚洲精品一区二三区不卡| 精品国产老师黑色丝袜高跟鞋| 国产精品久久国产精品99gif| 欧美激情在线观看视频| 国产精品久久久久不卡| 日本韩国欧美精品大片卡二| 日韩欧美国产免费播放| www.亚洲一区| 91亚洲精品在线观看| 亚洲免费电影在线观看| 欧美一区二三区| 久国内精品在线| 国产精品91免费在线| 欧美黄色小视频| 日韩精品免费在线播放| 日韩av电影院| 欧美综合国产精品久久丁香| 激情久久av一区av二区av三区| 2019中文字幕免费视频| 国产亚洲精品久久久久久| 国产精品免费电影| 91免费人成网站在线观看18| 国产xxx69麻豆国语对白| 高潮白浆女日韩av免费看| 欧美日韩在线免费观看| 欧美日韩国产999| 97激碰免费视频| 亚洲第一区在线| 国产日韩精品电影| 国产午夜精品视频免费不卡69堂| 久热爱精品视频线路一| 隔壁老王国产在线精品| 亚洲午夜性刺激影院| 欧美疯狂性受xxxxx另类| 欧美xxxx做受欧美| 久久人人爽人人爽人人片av高请| 国产精品第10页| 久久久久久久久久久久av| 欧美日韩国产限制| 久久久免费电影| 欧美韩日一区二区| 亚洲黄色av女优在线观看| 欧美激情亚洲国产| 国内精品模特av私拍在线观看| 亚洲久久久久久久久久久| 欧美午夜精品久久久久久久| 插插插亚洲综合网| 亚洲国产精品久久91精品| 久久人人看视频| 久久久久国色av免费观看性色| 欧美精品18videos性欧| 国产精品自产拍高潮在线观看| 国产精自产拍久久久久久蜜| 91在线播放国产| 久久精视频免费在线久久完整在线看| 亚洲第一国产精品| 成人精品视频99在线观看免费| 国产精品第七十二页| 精品少妇v888av| 91精品国产高清| 国产欧美va欧美va香蕉在| 这里只有精品在线播放| 久久综合五月天| 亚洲欧美在线看| 久久99精品国产99久久6尤物| 在线播放国产一区二区三区| 久久av.com| 亚洲电影第1页| 亚洲综合精品伊人久久| 国产97人人超碰caoprom| 亚洲理论片在线观看| 亚洲加勒比久久88色综合| 在线播放亚洲激情| 亚洲一区亚洲二区亚洲三区| 国产成人亚洲综合91| 国产亚洲视频中文字幕视频| 97在线视频免费播放| 午夜精品久久17c| 日韩欧美有码在线| 精品爽片免费看久久| 国产一区二区欧美日韩| 国产欧美精品一区二区三区-老狼| 8090理伦午夜在线电影| 国产日韩欧美在线视频观看| 成人免费自拍视频| 成人av.网址在线网站| 在线观看免费高清视频97| 热re91久久精品国99热蜜臀| 日韩电影第一页| 精品视频—区二区三区免费| 96精品视频在线| 亚洲天堂一区二区三区| 亚洲精品国产精品国自产在线| 国产亚洲a∨片在线观看| 中文字幕亚洲欧美一区二区三区| 久久久久久国产免费| 久久九九全国免费精品观看| 激情懂色av一区av二区av| 欧美大全免费观看电视剧大泉洋| 欧美丝袜美女中出在线| 欧美人在线观看| 欧美日韩另类字幕中文| 欧美黑人视频一区| 九九热这里只有精品免费看| 青草热久免费精品视频| 69视频在线播放| 成人在线中文字幕| 国产精品一区二区久久| 亚洲国产欧美精品| 永久免费看mv网站入口亚洲| 欧美疯狂做受xxxx高潮| www.亚洲一二| 97在线精品国自产拍中文| 日韩欧美有码在线| 日韩有码片在线观看| 亚洲欧美另类国产| 亚洲自拍偷拍区| 久久99久国产精品黄毛片入口| 国产精品劲爆视频| 亚洲天堂男人天堂| 亚洲大胆美女视频| www.久久色.com| 亚洲成人在线视频播放| 欧美日韩日本国产| 国产成人激情视频| 91爱视频在线| 日韩精品免费在线播放| 91在线直播亚洲| 奇门遁甲1982国语版免费观看高清| 欧美日韩国内自拍| www.亚洲人.com| 久久亚洲欧美日韩精品专区| 91av免费观看91av精品在线| 国产日韩视频在线观看| 91久久中文字幕| 播播国产欧美激情| 琪琪第一精品导航|