static關(guān)鍵字的再思考

引言

? ? ? ?static關(guān)鍵字在c/c++中的使用是十分廣泛的礁蔗。該關(guān)鍵字的作用很多突硝,其中一個(gè)最常用的作用就是對(duì)函數(shù)或者變量進(jìn)行隱藏:沒有添加static的變量或者函數(shù)是全局可見的螃宙;而添加了static關(guān)鍵字的全局變量則被隱藏蛮瞄,利用這一特性可以在不同的文件中定義同名函數(shù)和同名變量,而不必?fù)?dān)心命名沖突谆扎。
? ? ? ?現(xiàn)在挂捅,如果想在.h文件中定義static變量,將它強(qiáng)行暴露出來堂湖,會(huì)發(fā)生什么情況呢闲先?為了解決這一疑惑,筆者在windows下的vs2010環(huán)境中進(jìn)行了試驗(yàn)无蜂。

Context

試驗(yàn)一:

? ? ? ?筆者現(xiàn)在創(chuàng)建一個(gè)工程目錄伺糠,目錄結(jié)構(gòu)如下:

~/workspace/Test
  |-src
  |  |-A.h
  |  |-B.h
  |  |-main.cpp
  |  |-B.cpp
  |-doc
  |  |-Test.txt
  |-COPYRIGHT
  |-README

? ? ? ?頭文件A.h,主要作用是在頭文件A中定義了static變量a斥季,將變量a暴露出來训桶。

#ifndef _A_H_
#define _A_H_
static int a=0;

#endif

? ? ? ?頭文件B.h,聲明了函數(shù)funB()酣倾,同時(shí)引入了頭文件A.h舵揭。

#ifndef _B_H_
#define _B_H_

#include "A.h"
void funB();

#endif

? ? ? ?B.cpp文件,定義了函數(shù)funB()躁锡。

#include "B.h"
#include<iostream>
using namespace std;

void funB()
{
    cout<<"funB(): &a = "<<&a<<" , a = "<<a<<endl;
}

? ? ? ?main.cpp文件午绳。

#include <iostream>
#include "A.h"
#include "B.h"
using namespace std;

int main()
{
    
    cout<<"main1(): &a = "<<&a<<" , a = "<<a<<endl;
    a++;
    cout<<"main2(): &a = "<<&a<<" , a = "<<a<<endl;
    funB();
    system("pause");
    return 0;
}

? ? ? ?因?yàn)閍定義在.h文件中,如果a是一個(gè)全局變量稚铣,對(duì)于main.cpp和B.cpp都是可見的箱叁,那么在main函數(shù)中,a的值應(yīng)該先為0惕医,在main的末尾耕漱,應(yīng)該為1,且a的地址都應(yīng)該是一樣的抬伺,但是螟够,vs2010顯示的結(jié)果如下:

試驗(yàn)一結(jié)果

? ? ? ?結(jié)果表明,mian.cpp讀取的a和B.cpp讀取的變量a是兩個(gè)不同的變量,擁有不同的地址空間妓笙,a在main.cpp和B.cpp中做到了互相獨(dú)立若河。也就是說定義在頭文件里的static變量,被其他模塊每包含一次就申請(qǐng)一次內(nèi)存寞宫!

試驗(yàn)二:

? ? ? ?保持其他文件不變萧福,只改變A.h中的static int a =0;。將這句話改為 int a = 0;辈赋,此時(shí)鲫忍,工程無法通過編譯,會(huì)報(bào)fatal error LNK1169: one or more multiply defined symbols found錯(cuò)誤钥屈,這個(gè)很好理解悟民,因?yàn)闆]有static修飾后的變量a是一個(gè)全局變量,在main.cpp中和B.cpp中在全局空間中同時(shí)定義了兩個(gè)名字相同的變量篷就,會(huì)導(dǎo)致重定義的錯(cuò)誤射亏。同時(shí)結(jié)合試驗(yàn)一也再一次論證了舌菜,全局變量#include多次會(huì)出錯(cuò)士葫,而static變量被#include多次會(huì)生成多個(gè)局部變量运挫。

試驗(yàn)三:

? ? ? ?筆者現(xiàn)在創(chuàng)建一個(gè)新的工程目錄迟几,目錄結(jié)構(gòu)如下:

~/workspace/Test
  |-src
  |  |-B.h
  |  |-main.cpp
  |  |-B.cpp
  |-doc
  |  |-Test.txt
  |-COPYRIGHT
  |-README

? ? ? ?頭文件B.h身辨。

#ifndef _B_H_
#define _B_H_

void funB();

#endif

? ? ? ?B.cpp文件匕垫,定義了函數(shù)funB()雏门。

#include "B.h"
#include<iostream>
using namespace std;
static int a = 0;

void funB()
{
    cout<<"funB(): &a = "<<&a<<" , a = "<<a<<endl;
}

? ? ? ?main.cpp文件泞莉。

#include <iostream>
#include "A.h"
#include "B.h"
using namespace std;
extern int a;

int main()
{
    
    cout<<"main1(): &a = "<<&a<<" , a = "<<a<<endl;
    a++;
    cout<<"main2(): &a = "<<&a<<" , a = "<<a<<endl;
    funB();
    system("pause");
    return 0;
}

? ? ? ?此時(shí)也會(huì)編譯報(bào)錯(cuò)鼎姐,報(bào)fatal error LNK1120: 1 unresolved externals钾麸,因?yàn)閟tatic關(guān)鍵字修飾了變量a,使得變量a是B.cpp獨(dú)占的炕桨,對(duì)main.cpp隱藏饭尝,即使用extern關(guān)鍵字修飾,main.cpp也無法解析献宫。

試驗(yàn)四:

? ? ? ?試驗(yàn)四在試驗(yàn)三的基礎(chǔ)上钥平,將B.cpp中的static int a = 0;修改為int a = 0;。缺少了static關(guān)鍵字修飾姊途,利用extern自然可以將B.cpp中的a暴露給 main.cpp涉瘾。
? ? ? ?試驗(yàn)結(jié)果如下:

試驗(yàn)四結(jié)果

總結(jié)

? ? ? ?上述的四次試驗(yàn)再一次證明了:變量不要在頭文件中定義,要在.cpp文件中定義捷兰!全局變量#include多次會(huì)出錯(cuò)立叛,而static變量被#include多次會(huì)生成多個(gè)局部變量。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末贡茅,一起剝皮案震驚了整個(gè)濱河市秘蛇,隨后出現(xiàn)的幾起案子其做,更是在濱河造成了極大的恐慌,老刑警劉巖赁还,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件妖泄,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡艘策,警方通過查閱死者的電腦和手機(jī)蹈胡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來柬焕,“玉大人审残,你說我怎么就攤上這事梭域“呔伲” “怎么了?”我有些...
    開封第一講書人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵病涨,是天一觀的道長(zhǎng)富玷。 經(jīng)常有香客問我,道長(zhǎng)既穆,這世上最難降的妖魔是什么赎懦? 我笑而不...
    開封第一講書人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮幻工,結(jié)果婚禮上励两,老公的妹妹穿的比我還像新娘。我一直安慰自己囊颅,他們只是感情好当悔,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著踢代,像睡著了一般盲憎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上胳挎,一...
    開封第一講書人閱讀 51,165評(píng)論 1 299
  • 那天饼疙,我揣著相機(jī)與錄音,去河邊找鬼慕爬。 笑死窑眯,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的医窿。 我是一名探鬼主播磅甩,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼留搔!你這毒婦竟也來了更胖?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎却妨,沒想到半個(gè)月后饵逐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡彪标,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年倍权,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片捞烟。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡薄声,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出题画,到底是詐尸還是另有隱情默辨,我是刑警寧澤,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布苍息,位于F島的核電站缩幸,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏竞思。R本人自食惡果不足惜表谊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望盖喷。 院中可真熱鬧爆办,春花似錦、人聲如沸课梳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)惦界。三九已至挑格,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間沾歪,已是汗流浹背漂彤。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留灾搏,地道東北人挫望。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像狂窑,于是被迫代替她去往敵國(guó)和親媳板。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

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

  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom閱讀 2,696評(píng)論 0 3
  • 在C語(yǔ)言中,五種基本數(shù)據(jù)類型存儲(chǔ)空間長(zhǎng)度的排列順序是: A)char B)char=int<=float C)ch...
    夏天再來閱讀 3,340評(píng)論 0 2
  • 1 原理 1.1 首先泉哈,關(guān)于聲明和定義的區(qū)別蛉幸。 這種寫法(函數(shù)原型后加;號(hào)表示結(jié)束的寫法)只能叫函數(shù)聲明而不能叫函...
    Pitfalls閱讀 6,485評(píng)論 2 12
  • 很喜歡馮唐的文字:簡(jiǎn)潔干練直白破讨,不裝不作不無病呻吟,有深度高度奕纫。 峰子自詡為:唐粉 嚴(yán)重認(rèn)同他認(rèn)為碼字人應(yīng):感受在...
    冰語(yǔ)夏蟲閱讀 542評(píng)論 0 3
  • Java 程序是如何跑起來的呢提陶,如何從一個(gè) .java 源文件到控制臺(tái)的輸出結(jié)果?要回答類似的問題就需要學(xué)習(xí)虛擬機(jī)...
    云大數(shù)據(jù)社區(qū)閱讀 580評(píng)論 0 8