一、讓自己習(xí)慣C++

第一章介紹 C++ 的一些基本方式洛搀。

1. 視 C++ 為一個語言聯(lián)邦

現(xiàn)在 C++ 已經(jīng)是個多重泛型編程語言敢茁,同時支持過程、面向?qū)ο罅裘馈⒑瘮?shù)彰檬、泛型伸刃、元編程形式。將其視為語言聯(lián)邦逢倍,主要有四個次語言:

  • C
    區(qū)塊捧颅、語句、預(yù)處理较雕、內(nèi)置數(shù)據(jù)類型碉哑、數(shù)組、指針都來自C亮蒋。此時傳值比傳引用高效扣典。
  • Object-Oriented C++
    類(構(gòu)造、析構(gòu)函數(shù))慎玖、封裝贮尖、繼承、多態(tài)趁怔、虛函數(shù)湿硝。傳引用比傳值高效。
    -Template C++
    新的編程范型:模板元編程
  • STL
    容器痕钢、迭代器图柏、算法、函數(shù)對象任连。傳值更高效。

總結(jié):

C++ 高效編程守則視狀況而變化例诀,取決于使用 C++ 的哪一部分随抠。

2. 盡量以const, enum, inline 替換 #define

寧可以編譯器替換預(yù)處理器。#define不被視為語言的一部分繁涂,所以編譯出錯時難以查找拱她。如:

#define ASPECT_RATIO 1.653
應(yīng)換為
const double AspectRatio = 1.653

此時AspectRatio會進(jìn)入編譯器的記號表,而且對于浮點(diǎn)數(shù)使用常量可能比 #define 碼量更小扔罪。常量替換 #define 的兩種特殊情況:

  1. 定義常量指針

    例如定義一個常量的char *-based字符串:
    改為 string 更合適:
  2. class專屬常量

    為了將常量的作用域限制在class中秉沼,需將其設(shè)為class的一個成員;要確保其只有一份實(shí)體矿酵,需聲明為static成員唬复。
    另外需要提供定義式才能取地址:

    一般形式為:
    但是當(dāng)這個常量用于指定數(shù)組大小,可改用“the enum hack”: 一個屬于枚舉類型的數(shù)值可權(quán)充 ints 被使用全肮。
    enum比較像#define, 取enum 地址不合法敞咧,但是取const地址合法。enums 與 #defines一樣絕不會導(dǎo)致非必要的內(nèi)存分配辜腺。

另一個#define的誤用是用它實(shí)現(xiàn)宏休建。如

首先寫起來麻煩乍恐,而且可能導(dǎo)致不可思議的問題:
改為:

產(chǎn)生一整群函數(shù),每個函數(shù)接受兩個同型對象测砂。

總結(jié)

  • 對于單純常量茵烈,最好以const對象或enums替換#define
  • 對于形如函數(shù)的宏,最好改用inline函數(shù)替換#define

3. 盡可能使用const

關(guān)鍵詞const 用于指定一個不該被改動的對象砌些,加上這個約束后編譯器會強(qiáng)制保證實(shí)施瞧毙。所以只要某個值確定應(yīng)該不變,就應(yīng)該加上以得到編譯器的幫助寄症。

當(dāng)const和指針組合時:

  • const出現(xiàn)在星號左邊——被指物是常量
  • const出現(xiàn)在星號右邊——指針自身是常量
  • 兩邊都有——被指物和指針都是常量

以相對指針的位置來判斷宙彪,所以以下兩種寫法相同:


當(dāng)const和STL迭代器組合時:迭代器的作用就像是 T* 指針。const 迭代器 = T* const 指針有巧,表示這個迭代器不得指向不同的東西释漆,但所指對象的值可變。如:
符號看起來有點(diǎn)易混淆篮迎。

當(dāng)const和函數(shù)聲明組合時:返回一個常量值

可以防止如下暴行:
顯然對于內(nèi)置類型來說式子不成立男图,良好的用戶自定義類型也應(yīng)該避免無端的與內(nèi)置類型不兼容,所以返回const常量可阻止這類錯誤甜橱。

const成員函數(shù)

const用于成員函數(shù)是為了保證該函數(shù)可作用于const對象逊笆。這類函數(shù)重要的理由:

  1. 使class接口比較容易被理解
  2. 使操作const對象成為可能

兩個函數(shù)如果只是常量性不同,可以重載岂傲。

程序中const對象大多用于傳指針或傳引用难裆,故以下的調(diào)用方式更常見:
調(diào)用方式

錯誤在于企圖對由const版的operator[]返回的const char &施行賦值。

const成員函數(shù)的兩種概念:

  1. bitwise constness認(rèn)為成員函數(shù)只有在不更改對象的任何成員變量時才能稱為const镊掖。所以const成員函數(shù)不能更改對象內(nèi)任何non-static成員變量乃戈。
    但一個更改了指針?biāo)肝锏某蓡T函數(shù)雖然不算const,若只有指針屬于對象亩进,那么不會引發(fā)編譯錯誤症虑。

最終改變了常量對象的值。

  1. logical constness
    由于存在以上的錯誤归薛,這里主張一個const成員函數(shù)可以修改它所處理的對象內(nèi)的某些bits谍憔。如:
    為了可以修改這兩個數(shù)據(jù),可用mutable釋放non-static成員變量的bitwise constness約束主籍。

在const和non-const成員函數(shù)中避免重復(fù)

有時候成員函數(shù)需要進(jìn)行多個步驟习贫,這就造成const和non-const成員函數(shù)存在大量重復(fù):

解決辦法是常量性轉(zhuǎn)除,即用non-const調(diào)用const函數(shù)崇猫。
有兩個轉(zhuǎn)型動作沈条,若non-const函數(shù)單純調(diào)用operator[]會遞歸調(diào)用自己。所以第一次是 *this轉(zhuǎn)為const诅炉,第二次是從const operator[]的返回值中移除const蜡歹。使用static-cast做安全轉(zhuǎn)型屋厘,用const-cast移除const。

值得注意的是反向調(diào)用是錯誤的月而。用const調(diào)用non-const冒著對象被改的風(fēng)險汗洒。

總結(jié)

  • 將某些東西聲明為const可幫助編譯器偵測出錯誤用法。const可被施加于任何作用域內(nèi)的對象父款、函數(shù)參數(shù)溢谤、函數(shù)返回類型、成員函數(shù)本體憨攒。
  • 編譯器強(qiáng)制實(shí)施bitwise constness世杀,但編寫程序時應(yīng)使用概念上的常量性。
  • 當(dāng)const和non-const成員函數(shù)有著實(shí)質(zhì)等價的實(shí)現(xiàn)時肝集,令non-const版本調(diào)用const版本可避免代碼重復(fù)瞻坝。

4. 確定對象使用前已先被初始化

C++ 變量在聲名時有時會被初始化有時不會,需手工完成杏瞻。

至于內(nèi)置類型外的東西所刀,要確保每一個構(gòu)造函數(shù)都將對象的每一個成員初始化。但不要混淆賦值與初始化:
而C++規(guī)定:對象的成員變量的初始化操作發(fā)生在進(jìn)入構(gòu)造函數(shù)本體之前捞挥。較好的寫法是用成員初值列:

此時省去了default構(gòu)造的過程浮创,都進(jìn)行copy構(gòu)造。也可在列用default構(gòu)造:

而且如果成員變量是const或reference就一定需要初值砌函,不能被賦值斩披。所以最簡單的做法就是:總是使用成員初值列。

C++ 也有固定的成員初始化次序:基類早于子類胸嘴,類的成員變量總是以其聲明次序被初始化雏掠。

non-local static對象的初始化次序

所謂static對象,壽命從被構(gòu)造出來到程序結(jié)束為止劣像。也包括global對象,其中函數(shù)內(nèi)的static對象為local的摧玫。它們的析構(gòu)函數(shù)會在main函數(shù)結(jié)束時自動調(diào)用耳奕。

現(xiàn)在客戶建立如下類處理文件目錄:


此時就必須保證tfs在tempDir之前被初始化。正確的做法是 將每個non-local static對象搬到自己的專屬函數(shù)內(nèi)诬像,即用local static對象替換non-local static對象屋群。這么做的基礎(chǔ)是:C++ 保證函數(shù)內(nèi)static對象會在該函數(shù)被調(diào)用期間首次遇上該對象的定義式時被初始化。如:

現(xiàn)在使用函數(shù)返回的指向static對象的reference坏挠,而不再使用static對象自身芍躏。
所以為了避免初始化之前使用對象需要做:

  1. 手工初始化內(nèi)置型non-member對象
  2. 使用成員初值列對付對象的所有成分
  3. 在初始化次序不確定時用函數(shù)返回的指向static對象的reference。

總結(jié)

  1. 為內(nèi)置型對象進(jìn)行手工初始化降狠,C++不保證初始化对竣。
  2. 構(gòu)造函數(shù)最好使用成員初值列庇楞,不要再構(gòu)造函數(shù)本體內(nèi)用賦值操作。初值列列出的變量次序應(yīng)與聲明次序同
  3. 為免除“跨編譯單元的初始化次序”問題否纬,用local static對象替換non-local static對象吕晌。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市临燃,隨后出現(xiàn)的幾起案子睛驳,更是在濱河造成了極大的恐慌,老刑警劉巖膜廊,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件乏沸,死亡現(xiàn)場離奇詭異,居然都是意外死亡爪瓜,警方通過查閱死者的電腦和手機(jī)蹬跃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來钥勋,“玉大人炬转,你說我怎么就攤上這事∷憔模” “怎么了扼劈?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長菲驴。 經(jīng)常有香客問我荐吵,道長,這世上最難降的妖魔是什么赊瞬? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任先煎,我火速辦了婚禮,結(jié)果婚禮上巧涧,老公的妹妹穿的比我還像新娘薯蝎。我一直安慰自己,他們只是感情好谤绳,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布占锯。 她就那樣靜靜地躺著,像睡著了一般缩筛。 火紅的嫁衣襯著肌膚如雪消略。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天瞎抛,我揣著相機(jī)與錄音艺演,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛胎撤,可吹牛的內(nèi)容都是我干的晓殊。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼哩照,長吁一口氣:“原來是場噩夢啊……” “哼挺物!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起飘弧,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤识藤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后次伶,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體痴昧,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年冠王,在試婚紗的時候發(fā)現(xiàn)自己被綠了赶撰。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡柱彻,死狀恐怖豪娜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情哟楷,我是刑警寧澤瘤载,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站卖擅,受9級特大地震影響鸣奔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜惩阶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一挎狸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧断楷,春花似錦锨匆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至账千,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間暗膜,已是汗流浹背匀奏。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留学搜,地道東北人娃善。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓论衍,卻偏偏與公主長得像,于是被迫代替她去往敵國和親聚磺。 傳聞我的和親對象是個殘疾皇子坯台,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評論 2 359

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

  • 1. 讓自己習(xí)慣C++ 條款01:視C++為一個語言聯(lián)邦 為了更好的理解C++,我們將C++分解為四個主要次語言:...
    Mr希靈閱讀 2,819評論 0 13
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,523評論 1 51
  • 1 讓自己習(xí)慣 C++ 條款01:視 C++ 為一個語言聯(lián)邦 將C++視為一個由相關(guān)語言組成的聯(lián)邦而非單一語言瘫寝。在...
    暗夜望月閱讀 373評論 0 1
  • C++文件 例:從文件income. in中讀入收入直到文件結(jié)束蜒蕾,并將收入和稅金輸出到文件tax. out。 檢查...
    SeanC52111閱讀 2,799評論 0 3
  • 現(xiàn)在開始上班了,很久沒有更新了.今天寫個collectionView給大家看看,這種樣式的collectionvi...
    徐老茂閱讀 893評論 3 12