国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C++ > 正文

讀書筆記_Effective_C++_條款四:確定對(duì)象被使用前已先被初始化

2019-11-08 03:20:20
字體:
供稿:網(wǎng)友

1. 內(nèi)置類型

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ù),比如:

復(fù)制代碼
 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 };復(fù)制代碼

當(dāng)聲明

A obj;

時(shí),obj的成員變量a,b和text就已經(jīng)獲得了初值,分別是0,0和hello world。

這里注意一下,有些C++的初學(xué)者喜歡這樣寫:

復(fù)制代碼
 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 };復(fù)制代碼

效果雖然和上一個(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è)例子,將之改成:

復(fù)制代碼
 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 };復(fù)制代碼

雖然初始化列表的順序是b在先,但編譯器只會(huì)根據(jù)聲明變量時(shí)的先后順序,所以還是a被先初始化,想要用以下這種方式初始化的同學(xué)要當(dāng)心:

復(fù)制代碼
 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 };復(fù)制代碼

這一定不會(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ì)象。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 凤庆县| 长春市| 新泰市| 凤台县| 根河市| 茶陵县| 乌拉特前旗| 大宁县| 桑植县| 大同县| 莱芜市| 敦化市| 思南县| 白朗县| 岑溪市| 义马市| 依兰县| 杭州市| 永清县| 驻马店市| 旌德县| 且末县| 银川市| 沙洋县| 英德市| 顺义区| 全椒县| 松潘县| 沁源县| 浑源县| 深州市| 板桥市| 扶余县| 田东县| 阳信县| 朝阳区| 法库县| 雅江县| 琼中| 广宗县| 瑞金市|