C++中的內(nèi)置基本類型,比如int,double,float等,初值都是垃圾值,即聲明int i,i的初值是一個(gè)垃圾值。本書建議的最佳處理方法是:永遠(yuǎn)在使用對(duì)象之前將之初始化。比如:
1 int x = 0;2 3 const char* test = “hello world”;4 5 double d; cin >> d;2. STL
C++提供了豐富的容器,比如vector,list,deque,map和set等,這些容器已經(jīng)寫好了構(gòu)造函數(shù),所以總會(huì)自動(dòng)初始化成默認(rèn)值,程序員可以直接使用,比如:
vector<int> vt; vt.push_back(3);3. 自定義類
C++在類中有專門初始化成員變量的構(gòu)造函數(shù),程序員可以寫出合適的構(gòu)造函數(shù),比如:
1 class A 2 { 3 PRivate: 4 int a; 5 double b; 6 string text; 7 8 public: 9 A():a(0), b(0), text("hello world"){} //構(gòu)造函數(shù)10 };當(dāng)聲明
A obj;時(shí),obj的成員變量a,b和text就已經(jīng)獲得了初值,分別是0,0和hello world。
這里注意一下,有些C++的初學(xué)者喜歡這樣寫:
1 class A 2 3 { 4 private: 5 int a; 6 double b; 7 string text; 8 9 public:10 A()11 {12 a = 0;13 b = 0;14 text = "hello world";15 }16 17 };效果雖然和上一個(gè)例子一樣,都獲得了指定的初值,但執(zhí)行的效率卻不如上個(gè)例子。上一個(gè)例子中使用了成員初始化列表的方式,即在冒號(hào)后面逐一初始化,但本例卻在函數(shù)體內(nèi)進(jìn)行了初始化。事實(shí)上,本例其實(shí)不能嚴(yán)格稱為“初始化”,因?yàn)樵谶M(jìn)入構(gòu)造函數(shù)的函數(shù)體時(shí),這些成員變量已經(jīng)被初始化了,a和b初始化成垃圾值,string因?yàn)槭荢TL,調(diào)用默認(rèn)的構(gòu)造函數(shù)初始化為空字符串,在函數(shù)體內(nèi)進(jìn)行的操作實(shí)為“賦值”,也就是用新值覆蓋舊值。這也正是說它的執(zhí)行效率不高的原因,既進(jìn)行了初始化,又在之后進(jìn)行了賦值,不像上一個(gè)例子,只有初始化,一步到位。在有些特殊情況下,比如成員變量是const的或者是reference的,進(jìn)行初始化后值就不可以改變了,這時(shí)只能用初始化列表,不能在函數(shù)體內(nèi)賦值。
所以,應(yīng)該盡可能地采用有冒號(hào)的成員初始化列表。注意這里的用詞“盡可能地”,表示也不是所有情況都用這個(gè)初始化列表,當(dāng)想構(gòu)造的內(nèi)容復(fù)雜,或者已經(jīng)模塊化為函數(shù)了,這時(shí)不能用初始化列表的方式,就采用在函數(shù)體內(nèi)賦值的方式為好。
這里還有一個(gè)問題要注意下,當(dāng)使用初始化列表時(shí),初始成員變量的順序與列表排列的順序沒有關(guān)系,只取決于聲明這些成員變量的順序,還是那個(gè)例子,將之改成:
1 class A 2 { 3 private: 4 int a; 5 double b; 6 string text; 7 8 public: 9 A():b(0), a(0), text("hello world"){}10 };雖然初始化列表的順序是b在先,但編譯器只會(huì)根據(jù)聲明變量時(shí)的先后順序,所以還是a被先初始化,想要用以下這種方式初始化的同學(xué)要當(dāng)心:
1 class A 2 { 3 private: 4 int a; 5 double b; 6 string text; 7 8 public: 9 A():b(0), a(b), text("hello world"){}10 11 };這一定不會(huì)得到你想要的結(jié)果的,因?yàn)閍會(huì)首先初始化,而這時(shí)b尚未初始化,所以會(huì)有bug。本書中建議,為了避免這種順序不一致的晦澀錯(cuò)誤,“當(dāng)你在成員初值列中條列各個(gè)成員時(shí),最好總是以聲明次序?yàn)榇涡颉薄?/p>
4. 不同編譯單元內(nèi)定義的non-local static 對(duì)象
這里先解釋一下名詞,static是靜態(tài)的意思,表示這個(gè)變量不由棧分配,而存儲(chǔ)在特有的全局變量/靜態(tài)變量區(qū)域中,具有長壽命的特點(diǎn)(從被構(gòu)造出來,直到程序結(jié)束時(shí),才會(huì)由系統(tǒng)釋放資源);而non-local則是說這個(gè)對(duì)象是全局的,而不是函數(shù)內(nèi)的靜態(tài)變量,是說它的作用范圍廣。本博客中
http://www.cnblogs.com/jerry19880126/archive/2012/12/22/2829394.html
介紹了有關(guān)函數(shù)作域和生存周期的區(qū)別。
比如在文件1中定義了
int a = 1;而在文件2中又會(huì)去使用:
extern int a;int b = a *3;可以看到文件1應(yīng)在文件2之后執(zhí)行,這樣a才能獲得初值,否則b得到的將是垃圾值,但事實(shí)上C++對(duì)于不同文件執(zhí)行的相對(duì)次序并無明確定義,這樣b究竟得到的是垃圾值還是3就不能確定。
解決這個(gè)問題是方法是不要使變量有全局的作用域,可以在文件1中定義:
1 int& GetA()2 {3 static int a = 1;4 return a;5 }而在文件2中調(diào)用
int b = GetA();這樣就一定保證a的初始化在先了。
總結(jié)一下:
(1) 為內(nèi)置型對(duì)象進(jìn)行手工初始化,因?yàn)镃++不保證初始化它們;
(2) 構(gòu)造函數(shù)最好使用成員初始化列表(實(shí)際初始化順序不與列表的排列順序有關(guān),只取決于類中的聲明順序),而不要在構(gòu)造函數(shù)體內(nèi)使用賦值操作;
(3) 未避免“跨編譯單元的初始化次序”問題,請(qǐng)用local static代替non-local static對(duì)象。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注