static|extern|匿名空間

一 static用法

引用

1箕戳、限制作用域

這一點(diǎn)相對(duì)于普通全局變量和static全局變量來(lái)說(shuō)的惜互。
對(duì)于全局變量而言,不論是普通全局 變量還是static全局變量,其存儲(chǔ)區(qū)都是靜態(tài)存儲(chǔ)區(qū),因此在內(nèi)存分配上沒(méi)有什么區(qū)別。

區(qū) 別在于:

1) (*extern)普通的全局變量和函數(shù)硫狞,其作用域?yàn)檎麄€(gè)程序或項(xiàng)目,外部文件(其它c(diǎn)pp文件)可以通過(guò)extern關(guān)鍵字訪問(wèn)該變量和函數(shù)晃痴。一般不提倡這種用法残吩,如果要在多個(gè)cpp文件間共享數(shù)據(jù),應(yīng)該將數(shù)據(jù)聲明為extern類型倘核。

在頭文件里聲明為extern:
extern int g_value; // 注意泣侮,不要初始化值
然后在其中任何一個(gè)包含該頭文件的cpp中初始化(一次)就好:
int g_value = 0; // 初始化一樣不要extern修飾,因?yàn)閑xtern也是聲明性關(guān)鍵字紧唱;
然后所有包含該頭文件的cpp文件都可以用g_value這個(gè)名字訪問(wèn)相同的一個(gè)變量活尊;

2)static全局變量和函數(shù),其作用域?yàn)楫?dāng)前cpp文件漏益,其它的cpp文件不能訪問(wèn)該變量和函數(shù)蛹锰。如果有兩個(gè)cpp文件聲明了同名的全局靜態(tài)變量,那么他們實(shí)際上是獨(dú)立的兩個(gè)變量绰疤。

static函數(shù)的好處是不同的人編寫不同的函數(shù)時(shí)铜犬,不用擔(dān)心自己定義的函數(shù),是否會(huì)與其它文件中的函數(shù)同名轻庆。

在頭文件中的static變量
如果在一個(gè)頭文件中聲明:
static int g_vaule = 0;
那么會(huì)為每個(gè)包含該頭文件的cpp都創(chuàng)建一個(gè)全局變量癣猾,但他們都是獨(dú)立的;所以也不建議這樣的寫法榨了,一樣不明確需要怎樣使用這個(gè)變量煎谍,因?yàn)橹皇莿?chuàng)建了一組同名而不同作用域的變量。

2龙屉、數(shù)據(jù)唯一性

這是C++對(duì)static關(guān)鍵字的重用呐粘。主要指靜態(tài)數(shù)據(jù)成員/成員函數(shù)。

表示屬于一個(gè)類而不是屬于此類的任何特定對(duì)象的變量和函數(shù). 這是與普通成員函數(shù)的最大區(qū)別, 也是其應(yīng)用所在, 比如在對(duì)某一個(gè)類的對(duì)象進(jìn)行計(jì)數(shù)時(shí), 計(jì)數(shù)生成多少個(gè)類的實(shí)例, 就可以用到靜態(tài)數(shù)據(jù)成員. 在這里面, static既不是限定作用域的, 也不是擴(kuò)展生存期的作用, 而是指示變量/函數(shù)在此類中的唯一性. 這也是”屬于一個(gè)類而不是屬于此類的任何特定對(duì)象的變量和函數(shù)”的含義. 因?yàn)樗菍?duì)整個(gè)類來(lái)說(shuō)是唯一的, 因此不可能屬于某一個(gè)實(shí)例對(duì)象的. (針對(duì)靜態(tài)數(shù)據(jù)成員而言, 成員函數(shù)不管是否是static, 在內(nèi)存中只有一個(gè)副本, 普通成員函數(shù)調(diào)用時(shí), 需要傳入this指針, static成員函數(shù)調(diào)用時(shí), 沒(méi)有this指針. )

static數(shù)據(jù)成員的初始化:

  • (1) 初始化在類體外進(jìn)行转捕,而前面不加static作岖,以免與一般靜態(tài)變量或?qū)ο笙嗷煜?/li>
  • (2) 初始化時(shí)不加該成員的訪問(wèn)權(quán)限控制符private,public等五芝。
  • (3) 初始化時(shí)使用作用域運(yùn)算符來(lái)標(biāo)明它所屬類痘儡,因此,靜態(tài)數(shù)據(jù)成員是類的成員枢步,而不是對(duì)象的成員沉删。
  • (4) 靜態(tài)數(shù)據(jù)成員是靜態(tài)存儲(chǔ)的渐尿,它是靜態(tài)生存期,必須對(duì)它進(jìn)行初始化矾瑰。

Static成員函數(shù)

靜態(tài)成員函數(shù)和靜態(tài)數(shù)據(jù)成員一樣砖茸,它們都屬于類的靜態(tài)成員,它們都不是對(duì)象成員殴穴。因此凉夯,對(duì)靜態(tài)成員的引用不需要用對(duì)象名。

靜態(tài)成員函數(shù)僅能訪問(wèn)靜態(tài)的數(shù)據(jù)成員采幌,不能訪問(wèn)非靜態(tài)的數(shù)據(jù)成員劲够,也不能訪問(wèn)非靜態(tài)的成員函數(shù),這是由于靜態(tài)的成員函數(shù)沒(méi)有this指針休傍。

3 在C語(yǔ)言中征绎,static的字面意思很容易把我們導(dǎo)入歧途,其實(shí)它的作用有三條磨取。

(1)先來(lái)介紹它的第一條也是最重要的一條:隱藏炒瘸。

當(dāng)我們同時(shí)編譯多個(gè)文件時(shí),所有未加static前綴的全局變量和函數(shù)都具有全局可見(jiàn)性寝衫。為理解這句話,我舉例來(lái)說(shuō)明拐邪。我們要同時(shí)編譯兩個(gè)源文件慰毅,一個(gè)是a.c,另一個(gè)是main.c扎阶。

下面是a.c的內(nèi)容

char a = 'A'; // global variable
void msg()
{
     printf("Hello\n");
}

下面是main.c的內(nèi)容

int main(void)
{    
    extern char a;    // extern variable must be declared before use
     printf("%c ", a);
     (void)msg();
    return 0;
}

程序的運(yùn)行結(jié)果是:

A Hello

你可能會(huì)問(wèn):為什么在a.c中定義的全局變量a和函數(shù)msg能在main.c中使用汹胃?前面說(shuō)過(guò),所有未加static前綴的全局變量和函數(shù)都具有全局可見(jiàn)性东臀,其它的源文件也能訪問(wèn)着饥。此例中,a是全局變量惰赋,msg是函數(shù)宰掉,并且都沒(méi)有加static前綴,因此對(duì)于另外的源文件main.c是可見(jiàn)的赁濒。

如果加了static轨奄,就會(huì)對(duì)其它源文件隱藏。例如在a和msg的定義前加上static拒炎,main.c就看不到它們了挪拟。利用這一特性可以在不同的文件中定義同名函數(shù)和同名變量,而不必?fù)?dān)心命名沖突击你。Static可以用作函數(shù)和變量的前綴玉组,對(duì)于函數(shù)來(lái)講谎柄,static的作用僅限于隱藏,而對(duì)于變量惯雳,static還有下面兩個(gè)作用朝巫。(2)static的第二個(gè)作用是保持變量?jī)?nèi)容的持久。存儲(chǔ)在靜態(tài)數(shù)據(jù)區(qū)的變量會(huì)在程序剛開(kāi)始運(yùn)行時(shí)就完成初始化吨凑,也是唯一的一次初始化捍歪。共有兩種變量存儲(chǔ)在靜態(tài)存儲(chǔ)區(qū):全局變量和static變量,只不過(guò)和全局變量比起來(lái)鸵钝,static可以控制變量的可見(jiàn)范圍糙臼,說(shuō)到底static還是用來(lái)隱藏的。雖然這種用法不常見(jiàn)恩商,但我還是舉一個(gè)例子变逃。

#include <stdio.h>

int fun(void){
    static int count = 10;    // 事實(shí)上此賦值語(yǔ)句從來(lái)沒(méi)有執(zhí)行過(guò)
    return count--;
}

int count = 1;
int main(void)
{    
     printf("global\t\tlocal static\n");
    for(; count <= 10; ++count)
         printf("%d\t\t%d\n", count, fun());    
    return 0;
}

程序的運(yùn)行結(jié)果是:

global          local static
1               10
2               9
3               8
4               7
5               6
6               5
7               4
8                3
9               2
10              1

(3)static的第三個(gè)作用是默認(rèn)初始化為0。其實(shí)全局變量也具備這一屬性怠堪,因?yàn)槿肿兞恳泊鎯?chǔ)在靜態(tài)數(shù)據(jù)區(qū)揽乱。在靜態(tài)數(shù)據(jù)區(qū),內(nèi)存中所有的字節(jié)默認(rèn)值都是0x00粟矿,某些時(shí)候這一特點(diǎn)可以減少程序員的工作量凰棉。比如初始化一個(gè)稀疏矩陣,我們可以一個(gè)一個(gè)地把所有元素都置0陌粹,然后把不是0的幾個(gè)元素賦值撒犀。如果定義成靜態(tài)的,就省去了一開(kāi)始置0的操作掏秩。再比如要把一個(gè)字符數(shù)組當(dāng)字符串來(lái)用或舞,但又覺(jué)得每次在字符數(shù)組末尾加’\0’太麻煩。如果把字符串定義成靜態(tài)的蒙幻,就省去了這個(gè)麻煩映凳,因?yàn)槟抢锉緛?lái)就是’\0’。不妨做個(gè)小實(shí)驗(yàn)驗(yàn)證一下邮破。

#include <stdio.h>

int a;
int main(void)
{
    int i;
    static char str[10];
     printf("integer: %d;   string: (begin)%s(end)", a, str);
    return 0;
}

程序的運(yùn)行結(jié)果如下

integer: 0; string: (begin)(end)

最后對(duì)static的三條作用做一句話總結(jié)诈豌。首先static的最主要功能是隱藏,其次因?yàn)閟tatic變量存放在靜態(tài)存儲(chǔ)區(qū)决乎,所以它具備持久性和默認(rèn)值0队询。

二 extern

extern修飾的關(guān)鍵字,具有文件外部鏈接构诚,但是聲明extern變量時(shí)蚌斩,編譯器并不會(huì)給這個(gè)變量分配內(nèi)存,在另外的文件中定義這個(gè)文件時(shí)才會(huì)為其分配內(nèi)存,一旦聲明了extern關(guān)鍵字送膳,對(duì)編譯器來(lái)意味著:

  • 這個(gè)變量聲明(即數(shù)據(jù)類型和變量名员魏,但是編譯器并沒(méi)有分配內(nèi)存)
  • 這個(gè)變量的定義在其他文件中(在定義變量的文件中編譯器才會(huì)為其分配內(nèi)存)

最好將extern變量的聲明放在頭文件中,將變量的定義放在一個(gè)源文件中叠聋。

1 頭文件 (參考2.1.1)
在頭文件里聲明為extern:
extern int g_value; // 注意撕阎,不要初始化值
然后在其中任何一個(gè)包含該頭文件的cpp中初始化(一次)就好:
int g_value = 0; // 初始化一樣不要extern修飾,因?yàn)閑xtern也是聲明性關(guān)鍵字碌补;
然后所有包含該頭文件的cpp文件都可以用g_value這個(gè)名字訪問(wèn)相同的一個(gè)變量虏束;

2 當(dāng)我們同時(shí)編譯多個(gè)文件時(shí),所有未加static前綴的全局變量和函數(shù)都具有全局可見(jiàn)性厦章。
參考2.3.1 與1相同

三 匿名空間

當(dāng)定義一個(gè)命名空間時(shí)镇匀,可以忽略這個(gè)命名空間的名稱:

namespce {
char c;
int i;
double d;
}

編譯器在內(nèi)部會(huì)為這個(gè)命名空間生成一個(gè)唯一的名字,而且還會(huì)為這個(gè)匿名的命名空間生成一條using指令袜啃。
(編譯器會(huì)為匿名空間在當(dāng)前源文件中生成一個(gè)唯一的名字汗侵,使當(dāng)前的文件對(duì)匿名空間中的變量可見(jiàn))
所以上面的代碼在效果上等同于:

namespace __UNIQUE_NAME_ {
char c;
int i;
double d;
}
using namespace __UNIQUE_NAME_;

在匿名命名空間中聲明的名稱也將被編譯器轉(zhuǎn)換,與編譯器為這個(gè)匿名命名空間生成的唯一內(nèi)部名稱(即這里的_UNIQUE_NAME)綁定在一起群发。還有一點(diǎn)很重要晰韵,就是這些名稱具有internal鏈接屬性,這和聲明為static的全局名稱的鏈接屬性是相同的熟妓,即名稱的作用域被限制在當(dāng)前文件中雪猪,無(wú)法通過(guò)在另外的文件中使用extern聲明來(lái)進(jìn)行鏈接。如果不提倡使用全局static聲明一個(gè)名稱擁有internal鏈接屬性起愈,則匿名命名空間可以作為一種更好的達(dá)到相同效果的方法浪蹂。
注意:命名空間都是具有external 連接屬性的,只是匿名的命名空間產(chǎn)生的UNIQUE_NAME在別的文件中無(wú)法得到,這個(gè)唯一的名字是不可見(jiàn)的.
C++ 新的標(biāo)準(zhǔn)中提倡使用匿名命名空間,而不推薦使用static,因?yàn)閟tatic用在不同的地方,涵義不同,容易造成混淆.另外,static不能修飾class

總結(jié)

static 常修飾變量或函數(shù) (與匿名空間左右類似,新標(biāo)準(zhǔn)推薦匿名空間)
extern 常修飾變量(對(duì)于函數(shù)沒(méi)必要告材,默認(rèn)是extern的)
詳細(xì)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市古劲,隨后出現(xiàn)的幾起案子斥赋,更是在濱河造成了極大的恐慌,老刑警劉巖产艾,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件疤剑,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡闷堡,警方通過(guò)查閱死者的電腦和手機(jī)隘膘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)杠览,“玉大人弯菊,你說(shuō)我怎么就攤上這事□獍ⅲ” “怎么了管钳?”我有些...
    開(kāi)封第一講書人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵钦铁,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我才漆,道長(zhǎng)牛曹,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任醇滥,我火速辦了婚禮黎比,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鸳玩。我一直安慰自己阅虫,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布怀喉。 她就那樣靜靜地躺著书妻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪躬拢。 梳的紋絲不亂的頭發(fā)上躲履,一...
    開(kāi)封第一講書人閱讀 49,749評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音聊闯,去河邊找鬼工猜。 笑死,一個(gè)胖子當(dāng)著我的面吹牛菱蔬,可吹牛的內(nèi)容都是我干的篷帅。 我是一名探鬼主播,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼拴泌,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼魏身!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起蚪腐,我...
    開(kāi)封第一講書人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤箭昵,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后回季,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體家制,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年泡一,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了颤殴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鼻忠,死狀恐怖涵但,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤贤笆,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布蝇棉,位于F島的核電站,受9級(jí)特大地震影響芥永,放射性物質(zhì)發(fā)生泄漏篡殷。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一埋涧、第九天 我趴在偏房一處隱蔽的房頂上張望板辽。 院中可真熱鬧,春花似錦棘催、人聲如沸劲弦。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)邑跪。三九已至,卻和暖如春呼猪,著一層夾襖步出監(jiān)牢的瞬間画畅,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工宋距, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留轴踱,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓谚赎,卻偏偏與公主長(zhǎng)得像淫僻,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子壶唤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 作者:zhonyong 鏈接:https://www.zhihu.com/question/25532384/an...
    踩在浪花上00閱讀 504評(píng)論 0 2
  • ”進(jìn)程是資源分配的最小單位闸盔,線程是CPU調(diào)度的最小單位“這樣的回答太抽象细办,不太容易讓人理解。做個(gè)簡(jiǎn)單的比喻:進(jìn)程=...
    Lydia1991閱讀 78評(píng)論 0 0
  • 線程和進(jìn)程的區(qū)別是什么岛啸? - 知乎 Swoole:面向生產(chǎn)環(huán)境的 PHP 異步網(wǎng)絡(luò)通信引擎 動(dòng)態(tài)語(yǔ)言并發(fā)處理_慕課...
    RunningWin_4c80閱讀 109評(píng)論 0 0
  • 1.并發(fā)和并行有什么區(qū)別钓觉? (來(lái)源——實(shí)戰(zhàn)Java高并發(fā)程序設(shè)計(jì)) 從嚴(yán)格意義.上來(lái)說(shuō),并行的多個(gè)任務(wù)是真的同時(shí)執(zhí)...
    f280b56f054f閱讀 327評(píng)論 0 1
  • 進(jìn)程是程序運(yùn)行和資源分配的基本單位坚踩,一個(gè)程序至少有一個(gè)進(jìn)程荡灾,一個(gè)進(jìn)程至少有一個(gè)線程。進(jìn)程在執(zhí)行過(guò)程中擁有獨(dú)立的內(nèi)存...
    在右_dd50閱讀 109評(píng)論 0 0