在決定寫這本書的時(shí)候我面臨的一個(gè)最大的問(wèn)題是:是否把C++加入到討論
中去。盡管我熟悉C++,但是我不得不用C 和匯編來(lái)寫幾乎所有我的嵌入式軟件。而且在嵌入式軟件界對(duì)于C++是否值得所產(chǎn)生的性能損失的問(wèn)題存有很大的爭(zhēng)議。一般認(rèn)為C++程序會(huì)產(chǎn)生更大的代碼,這些代碼執(zhí)行起來(lái)比完全用C寫的程序要慢。然而,C++給于程序員很多好處,并且我想在這本書中討論一些這樣的好處。因此,我最終決定把C++加入到討論中來(lái),但是在我的例子中只是使用那些性能損失最小的特性。
我相信很多的讀者在他們自己的嵌入式系統(tǒng)編程的時(shí)候會(huì)面對(duì)相同的問(wèn)題。在結(jié)束這本書之前。我想簡(jiǎn)單地評(píng)判一下每一種我使用過(guò)的C++特性。并且提醒你一些我沒(méi)有使用過(guò)的比較昂貴的特性。
當(dāng)然,并不是每一件C++引入的事情都是昂貴的。很多老的C++tb編譯器并入了一個(gè)叫作C.front 的技術(shù),這項(xiàng)技術(shù)把C++的程序變成C,并且把結(jié)果供給標(biāo)準(zhǔn)的C 編譯器。這個(gè)事實(shí)暗示這兩種語(yǔ)言之間的句法差別很小,或與運(yùn)行代價(jià)無(wú)關(guān)(注2)。只有最新的C++特性,如模板,不能夠用這種方式處理。
比如,類的定義是完全有益的。公有和私有成員數(shù)據(jù)及函數(shù)的列表與一個(gè)struct 及函數(shù)原型的列表沒(méi)有大的差別。然而,C++編譯器能夠用public 和private 關(guān)鍵字決定,哪一個(gè)方法調(diào)用和數(shù)據(jù)訪問(wèn)是允許的或者是不允許的。因?yàn)檫@個(gè)決定在編譯的時(shí)候完成,所以運(yùn)行時(shí)不會(huì)付出代價(jià)。單純的加入類既不會(huì)影響代碼的大小,又不會(huì)影響你的程序的效率。
默認(rèn)參數(shù)值也是沒(méi)有損失的。編譯器只是加入代碼使得在每次函數(shù)被無(wú)參數(shù)調(diào)用的時(shí)候傳遞一個(gè)默認(rèn)的值。類似地,函數(shù)名的重載也是編譯時(shí)的修改。具有相同名字但是不同參數(shù)的函數(shù)在編譯過(guò)程中分別分配了一個(gè)唯一的名字。每次函數(shù)名出現(xiàn)在程序中的時(shí)候編譯器就替換它,然后連接器正確的把它們匹配起來(lái)。我沒(méi)有在我的例子中使用C++的這一特性,但是我這幺做過(guò)而沒(méi)有影響性能。
操作符的重載是另一個(gè)我使用過(guò)但是沒(méi)有包括在例子中的特性。無(wú)論何時(shí)編譯器見到這樣一個(gè)操作符,它只是用合適的函數(shù)調(diào)用來(lái)替換它。因此,在下面列出的代碼,最后兩行是等價(jià)的,性能的損失很容易明白:
Complex a, b, c;
c = operator+(a, b)
// The traditional way: Function Call
// The C++ way: Operator Overloading
構(gòu)造函數(shù)和析構(gòu)函數(shù)也有一點(diǎn)與它們相關(guān)的損失。這些特殊的方法去分別保證每次這種類型的tbw對(duì)象在創(chuàng)建或者超出了范圍時(shí)被調(diào)用。然而,這個(gè)小量的開銷是為減少錯(cuò)誤而支付的一個(gè)合理代價(jià)。構(gòu)造函數(shù)完整地刪除了一個(gè)C 語(yǔ)言編程中與未初始化數(shù)據(jù)結(jié)構(gòu)編程錯(cuò)誤有關(guān)的類。這個(gè)特性也被證明是有用的,因?yàn)樗[藏了那些與像Timer 和Task 這樣復(fù)雜的類相關(guān)的笨拙初始化順序。
虛擬函數(shù)也具有一個(gè)合理的代價(jià)收益比。不要深究太多的關(guān)于什么是虛擬函數(shù)的細(xì)節(jié),讓我們只是說(shuō)一下沒(méi)有它們多態(tài)性就是不可能的。而沒(méi)有多態(tài)性,C++就不可能是一個(gè)真正的面向?qū)ο蟮恼Z(yǔ)言。虛擬函數(shù)唯一一個(gè)明顯的代價(jià)是在調(diào)用虛擬函數(shù)之前附加了一個(gè)存儲(chǔ)查詢。普通的函數(shù)和方法調(diào)用是不受影響的。就我的體驗(yàn)來(lái)說(shuō)太昂貴的 C++特性有模板、異常事件及運(yùn)行類型識(shí)別。這三個(gè)特性都對(duì)代碼的大小有負(fù)面的影響,而且異常事件和運(yùn)行時(shí)類型識(shí)別還會(huì)增加執(zhí)行時(shí)間。在決定是否使用這些特性之前,你可能要做一些實(shí)驗(yàn)來(lái)看看它們會(huì)怎么樣影響你自己的應(yīng)用程序的大小及速度。