王 威,孫曉范,楊志敏
(1.山東外事翻譯職業(yè)學(xué)院,山東 威海 264504;2.山東大學(xué) 機(jī)電與信息工程學(xué)院,山東 威海 264209)
C++高層次抽象效率分析
王 威1,孫曉范1,楊志敏2
(1.山東外事翻譯職業(yè)學(xué)院,山東 威海 264504;2.山東大學(xué) 機(jī)電與信息工程學(xué)院,山東 威海 264209)
一開(kāi)始C++是作為C語(yǔ)言的增強(qiáng)版出現(xiàn)的,從增加類開(kāi)始,C語(yǔ)言不斷地增加新特性。在學(xué)習(xí)C++時(shí)可以將其作為一門獨(dú)立的語(yǔ)言,因?yàn)槠洳⒉灰蕾囉贑語(yǔ)言。《Thinking in C++》認(rèn)為在運(yùn)行效率上往往有一個(gè)±5%的差異。有說(shuō)法認(rèn)為高層次的抽象功能導(dǎo)致了C++的效率下降。為驗(yàn)證這個(gè)問(wèn)題,文章就一些有代表性的案例在封裝、繼承和多態(tài)的性能,并部分與C和Java語(yǔ)言進(jìn)行的比較,對(duì)引起效率下降的可能原因作出總結(jié),并給予相應(yīng)的解決方案。
C++;高層次抽象;面向?qū)ο?;編譯優(yōu)化
C++有3種編程范型:面向過(guò)程編程、面向?qū)ο缶幊毯头盒途幊蹋瑢?duì)應(yīng)3個(gè)抽象級(jí)別:過(guò)程抽象、數(shù)據(jù)抽象和模板[1]。高層次抽象涉及的是后面兩項(xiàng)。一般來(lái)說(shuō),抽象水平越高,越有利于分析和處理實(shí)際問(wèn)題。但同時(shí)可能會(huì)導(dǎo)致程序的性能下降。面向?qū)ο缶幊绦枰褂妙惖姆庋b、繼承和多態(tài)。封裝需要預(yù)先定義數(shù)據(jù)成員和類成員,使得程序變得累贅和臃腫。類的繼承則加劇了這種麻煩,因?yàn)樽宇惗家獜钠浠惱^承類的成員。這使得高層次抽象看起來(lái)比面向過(guò)程編程在編程空間上負(fù)擔(dān)更加沉重。另一方面,多態(tài)意味著我們必須花費(fèi)額外的時(shí)間做動(dòng)態(tài)數(shù)據(jù)類型綁定。C++在盡可能地確保運(yùn)行效率的前提下提供高層次抽象。在這里我們通過(guò)測(cè)試應(yīng)用程序分析C++的抽象機(jī)制并不時(shí)與其他語(yǔ)言做比較,來(lái)驗(yàn)證高層次抽象的表現(xiàn)。
C++支持各種不同的編程方法,這就是所謂的多范式編程,允許程序員針對(duì)不同的問(wèn)題選擇適當(dāng)?shù)哪J?。這里我們只討論高層次抽象的部分,對(duì)應(yīng)數(shù)據(jù)抽象和模板。
面向?qū)ο缶幊虣C(jī)制包括封裝、繼承和多態(tài),還有友元和內(nèi)聯(lián)機(jī)制。
1.1.1 封裝和繼承
封裝主要靠類實(shí)現(xiàn)。類的實(shí)例被稱為對(duì)象,是面向?qū)ο缶幊痰幕A(chǔ)。一個(gè)類通常包含大量的數(shù)據(jù)成員和函數(shù)成員,使得其看起來(lái)像使用過(guò)多的內(nèi)存空間。事實(shí)上,C++只為對(duì)象的數(shù)據(jù)成員分配一個(gè)單獨(dú)的存儲(chǔ)空間。編譯器不將數(shù)據(jù)成員歸入對(duì)象。
編譯和運(yùn)行如圖1所示中的代碼,可以得到結(jié)果是8。這里有兩個(gè)數(shù)據(jù)成員,一個(gè)函數(shù)成員和一個(gè)友元類,但只有數(shù)據(jù)成員消耗存儲(chǔ)空間。一個(gè)int類型的a占用4個(gè)字節(jié),一個(gè)bool類型的b占用1個(gè)字節(jié),根據(jù)C++中的對(duì)齊原則,系統(tǒng)分配另外4個(gè)字節(jié)以保持空間容易讀寫。我們可以看到函數(shù)成員和友元類的空間分配[2]。如果有一個(gè)從B派生出的子類,有自己的新數(shù)據(jù)成員和函數(shù)成員,同樣也會(huì)有從B中繼承的成員。但是我們可以驗(yàn)證系統(tǒng)只為子類中新添加的數(shù)據(jù)成員和從B中派生的成員分配空間。因此其和C語(yǔ)言中具有同樣數(shù)據(jù)成員的structure占據(jù)同樣的內(nèi)存空間。
圖1 一個(gè)典型的類
C++中對(duì)函數(shù)成員的處理是做對(duì)象到函數(shù)的映射。這是在編譯時(shí)進(jìn)行的所以是靜態(tài)綁定。函數(shù)成員通過(guò)隱藏的this指針訪問(wèn)數(shù)據(jù)成員,這也是唯一可能降低時(shí)間效率的因素。但是在C語(yǔ)言中只包含數(shù)據(jù)成員和一個(gè)獨(dú)立的函數(shù)來(lái)實(shí)現(xiàn)相同功能的structure同樣也需要一個(gè)指針來(lái)傳遞給構(gòu)造函數(shù)。因此在時(shí)間開(kāi)銷上,使用類的C++程序和使用相同功能結(jié)構(gòu)的C語(yǔ)言程序沒(méi)有太大區(qū)別。
C++的性能與對(duì)象的邏輯存儲(chǔ)位置也有關(guān)。C++的對(duì)象可以被分配在兩個(gè)位置:堆和棧。同一對(duì)象在堆和棧中分布會(huì)有不同的表現(xiàn)。棧對(duì)象在程序進(jìn)入函數(shù)體的時(shí)候完成創(chuàng)建,而堆對(duì)象是在程序運(yùn)行到new語(yǔ)句時(shí)開(kāi)始創(chuàng)建,意味著它創(chuàng)建一個(gè)新的類實(shí)例。管理堆對(duì)象的時(shí)間開(kāi)銷很大。如果我們?cè)诔绦蜻\(yùn)行時(shí)做了動(dòng)態(tài)內(nèi)存分配和回收,內(nèi)存空間中將會(huì)出現(xiàn)碎片[3]。如果存儲(chǔ)碎片太多,操作系統(tǒng)必須花費(fèi)額外的時(shí)間做整理而導(dǎo)致堆對(duì)象的存儲(chǔ)管理時(shí)間開(kāi)銷迅速增加。C++僅在程序剛開(kāi)始的時(shí)候使用堆對(duì)象,這時(shí)候還沒(méi)有產(chǎn)生內(nèi)存碎片。相對(duì)于只是用堆對(duì)象的Java,C++使用棧使得其運(yùn)營(yíng)效率表現(xiàn)往往要比Java好。
從上面的分析可以看出C++的類機(jī)制不增加運(yùn)行時(shí)開(kāi)銷。堆棧的使用讓C++具有更好的存儲(chǔ)管理性能。
1.1.2 運(yùn)行時(shí)多態(tài)
運(yùn)行時(shí)多態(tài),又稱動(dòng)態(tài)多態(tài)是面向?qū)ο缶幊痰暮诵奶卣鳌_@是通過(guò)延遲對(duì)象和操作的綁定至運(yùn)行時(shí)實(shí)現(xiàn)的,因此稱之為動(dòng)態(tài)多態(tài)。C++運(yùn)行時(shí)多態(tài)是基于虛函數(shù)機(jī)制的。
要使一個(gè)函數(shù)顯示多態(tài)性,必須聲明其為一個(gè)虛函數(shù)。包含虛函數(shù)的類被稱為多態(tài)類,其中的對(duì)象存儲(chǔ)方式已經(jīng)改變,除了前面提到的數(shù)據(jù)成員,還加上了一個(gè)虛函數(shù)表指針。該指針指向一個(gè)虛函數(shù)表,其中每個(gè)項(xiàng)目對(duì)應(yīng)一個(gè)虛函數(shù)地址。這些虛函數(shù)包括他們自己的對(duì)象和從基類的虛函數(shù)繼承來(lái)的部分[4]。虛函數(shù)表為類中所有對(duì)象共享。
如圖2所示,與普通類相比,多態(tài)類的對(duì)象添加一個(gè)指向內(nèi)存的指針。要訪問(wèn)虛函數(shù),必須要有個(gè)指針間的訪問(wèn)操作,這會(huì)成為影響性能的一個(gè)重要因素。因此運(yùn)行時(shí)多態(tài)確實(shí)增加了程序的時(shí)間和空間開(kāi)銷。更重要的是,虛函數(shù)不能被內(nèi)聯(lián)?;谶@些原因,為節(jié)約系統(tǒng)資源,虛函數(shù)的使用應(yīng)盡可能限制。
圖2 虛擬功能機(jī)制
1.1.3 編譯時(shí)多態(tài)
由于運(yùn)行時(shí)多態(tài)降低程序性能,我們被迫采取其他的措施來(lái)實(shí)現(xiàn)多態(tài),這就是編譯時(shí)多態(tài)。C++中有兩種方法實(shí)現(xiàn)這一機(jī)制:函數(shù)重載和模板。
函數(shù)重載是指用相同的名稱來(lái)定義不同的參數(shù)(可以是不同類型或不同數(shù)目的參數(shù))。重載可以發(fā)生在同一類中或者繼承中。然而當(dāng)固定參數(shù)的函數(shù)需要表現(xiàn)出多態(tài)時(shí),重載無(wú)能為力,因?yàn)槿绻宇愔匦露x的函數(shù)中具有與祖先類中的參數(shù)相同的名稱,這時(shí)并沒(méi)有發(fā)生重載,只是在子類函數(shù)中覆蓋基類。這意味著重載不能代替虛函數(shù)機(jī)制。
模板也成為參數(shù)化類型。當(dāng)編譯器遇到一個(gè)模板調(diào)用語(yǔ)句,它會(huì)產(chǎn)生函數(shù)定義或者類定義的參數(shù)類型,這叫作模板實(shí)例化。模板實(shí)例化的本質(zhì)就是模板與特定類型的綁定。綁定發(fā)生在編譯過(guò)程中,因此屬于靜態(tài)綁定。與動(dòng)態(tài)綁定不同靜態(tài)綁定不會(huì)導(dǎo)致程序運(yùn)行效率的下降。所以模板多態(tài)往往比運(yùn)行時(shí)多態(tài)有更好的效率優(yōu)勢(shì)。
另一方面,模板類經(jīng)常使用嵌套類型來(lái)定義自己與外界之間的接口。一個(gè)典型的例子是在標(biāo)準(zhǔn)模板庫(kù)(Standard Template Library,STL)中廣泛使用的容器,常用嵌套定義自己的迭代器。這可能會(huì)導(dǎo)致代碼膨脹,增加出錯(cuò)概率。
1.1.4 內(nèi)聯(lián)
在封裝原則的基礎(chǔ)上,類的數(shù)據(jù)成員是不開(kāi)放的,這意味著如果外部函數(shù)想要訪問(wèn)它們只能通過(guò)成員訪問(wèn)函數(shù)(典型是一個(gè)set和get)。如果一個(gè)函數(shù)需要訪問(wèn)很多數(shù)據(jù)成員,這個(gè)函數(shù)就會(huì)被頻繁調(diào)用,會(huì)導(dǎo)致程序性能的顯著下降。內(nèi)聯(lián)機(jī)制就是為了解決這一問(wèn)題出現(xiàn)的。
從源代碼來(lái)看,內(nèi)聯(lián)函數(shù)有函數(shù)的結(jié)構(gòu)但是在編譯時(shí)沒(méi)有函數(shù)的性質(zhì)。在編譯過(guò)程中,它使用函數(shù)體代替函數(shù)名。為了讀寫private或protected成員,必須使用接口功能。如果我們定義這些函數(shù)為內(nèi)聯(lián)成員函數(shù),會(huì)得到更好的效率。
但是內(nèi)聯(lián)機(jī)制有一定的局限性。當(dāng)內(nèi)聯(lián)函數(shù)過(guò)小并且返回值是一個(gè)復(fù)雜的對(duì)象時(shí),性能上的優(yōu)勢(shì)是最明顯的。但如果函數(shù)體本身很大,或者它內(nèi)部又調(diào)用了其他的內(nèi)聯(lián)函數(shù)(或switch語(yǔ)句的使用造成的遞歸),代碼不僅不能有更好的性能,反而會(huì)發(fā)生膨脹。一般情況下,我們所定義的函數(shù)體都很大,所以內(nèi)聯(lián)機(jī)制應(yīng)謹(jǐn)慎使用。
1.1.5 友元
在默認(rèn)配置下,編譯器可以決定是否把內(nèi)聯(lián)函數(shù)處理成普通的函數(shù)以避免可能出現(xiàn)的副作用,所以內(nèi)聯(lián)機(jī)制并非普遍適用。解決這一問(wèn)題要用到友元機(jī)制。
友元是一個(gè)在類外定義的函數(shù)或者類,在類體前標(biāo)注關(guān)鍵字friend來(lái)和類中的成員函數(shù)做區(qū)別。友元不是一個(gè)成員函數(shù),但可以訪問(wèn)類的私有成員[5]。雖然這種機(jī)制破壞了類的封裝,但它的確可以保證某些程序的運(yùn)行效率。例如,矩陣的乘法運(yùn)算函數(shù)通常會(huì)被聲明為一個(gè)矩陣類的友元。
在Java中,類的私有成員不能從外部訪問(wèn)。然而,Java使用一個(gè)默認(rèn)的訪問(wèn)機(jī)制,以限制同一個(gè)包中的數(shù)據(jù)成員,這在一定程度上減輕了函數(shù)經(jīng)常訪問(wèn)數(shù)據(jù)成員所造成的性能下降。顯然,Java中的訪問(wèn)控制機(jī)制不如C++中精細(xì)。
泛型編程最初提出的動(dòng)機(jī)是想要發(fā)明一種語(yǔ)言機(jī)制來(lái)幫助實(shí)現(xiàn)一個(gè)通用標(biāo)準(zhǔn)容器庫(kù)。泛型表示對(duì)各種類似于模板的數(shù)據(jù)類型都具有可操作性。泛型編程包括類模板和函數(shù)模板,具體到C++中的STL,可以分為6個(gè)主要的組成部分:分配器、迭代器、容器、算法、函數(shù)對(duì)象和適配器[6]。
1.2.1 分配器
許多C++程序往往涉及大量的小對(duì)象創(chuàng)建和銷毀,例如STL中的樹節(jié)點(diǎn)和鏈表節(jié)點(diǎn)。這可能導(dǎo)致使用new/delete機(jī)制的程序時(shí)間效率下降。對(duì)象的創(chuàng)建和銷毀開(kāi)銷過(guò)重,頻繁的內(nèi)存分配和大量小對(duì)象碎片的回收都是原因。因此有必要引入一個(gè)特殊的分配程序來(lái)提高時(shí)間效率,這就是分配器。
準(zhǔn)備兩個(gè)程序,每個(gè)分配和回收一百萬(wàn)個(gè)小對(duì)象。一個(gè)使用常用的new/delete方式,另一個(gè)使用分配器。運(yùn)行它們,看到比較的結(jié)果。我們可以看到使用分配器的程序具有更好的運(yùn)行性能。這里是一個(gè)小測(cè)試,用一個(gè)典型的類person,數(shù)據(jù)成員有不同類型的gender,name和age還有一些get/set函數(shù)。本次測(cè)試的時(shí)間開(kāi)銷如圖3所示。
圖3 通用方法和分配器機(jī)制創(chuàng)建和銷毀100萬(wàn)個(gè)對(duì)象所消耗的平均時(shí)間
這僅僅是一個(gè)小測(cè)試。對(duì)于那些需要長(zhǎng)期運(yùn)行在服務(wù)器端的程序,內(nèi)存管理關(guān)系到程序的穩(wěn)定性。專用的存儲(chǔ)操作,有利于程序性能和操作系統(tǒng)管理內(nèi)存。在特定的情況下,使用分配器可以使模擬器、編譯器或其他類似的運(yùn)行時(shí)間快一倍。
1.2.2 迭代器
迭代器是STL中一種可以用來(lái)遍歷容器的部分或全部元素的對(duì)象。每個(gè)容器的類型必須通過(guò)內(nèi)嵌套定義提供自己的迭代器。因此,迭代器具有相同的接口不同的類型。迭代器有很多不同的功能,其可以將抽象容器和通用算法有機(jī)地聯(lián)系起來(lái)。容器、算法、迭代器之間的關(guān)系如圖4所示。
迭代器實(shí)際上是一個(gè)模板模仿指針行為以允許用戶訪問(wèn)容器中的元素。那么其和指針相比性能如何呢?這里我們?cè)O(shè)定3個(gè)評(píng)價(jià)標(biāo)準(zhǔn):迭代性能,取內(nèi)容性能和成員訪問(wèn)性能。迭代是指迭代器從現(xiàn)在的位置移動(dòng)到指定位置,取內(nèi)容是指移動(dòng)對(duì)象內(nèi)容到迭代器,成員訪問(wèn)是指訪問(wèn)迭代器關(guān)聯(lián)的成員。迭代器和指針std::vector都有這3個(gè)功能,我們使用這個(gè)指針和迭代器做測(cè)試比較。測(cè)試結(jié)果如圖5所示.
從上面的測(cè)評(píng)我們可以看出,與指針相比迭代器的時(shí)間開(kāi)銷是相當(dāng)大的。因此迭代操作應(yīng)避免出現(xiàn)在小規(guī)模的編程中。但是我們也不能因此否定其存在。由于迭代器的出現(xiàn),容易和算法獨(dú)立開(kāi)來(lái),這是指針?biāo)鶡o(wú)法做到的。
圖4 容器、算法、迭代器之間的關(guān)系
1.2.3 算法和函數(shù)對(duì)象
STL算法是一個(gè)處理容器和迭代器元素的模板類,和容器獨(dú)立。因?yàn)樵谌萜髦械脑仡愋涂梢愿淖儯惴ū仨毮軌蛱幚聿煌愋偷臄?shù)據(jù)。所以其需要程序傳遞類型作為參數(shù)的操作到算法。STL使用函數(shù)對(duì)象來(lái)解決問(wèn)題。函數(shù)對(duì)象是一個(gè)類,重載了operator(args,…)函數(shù),提供需要的操作。函數(shù)對(duì)象作為參數(shù)傳遞給算法,算法會(huì)得到需要的操作。
圖5 迭代器和指針之間的性能比較
Bjarne Stroutstrup做了一個(gè)特殊的測(cè)試,對(duì) fl oat和string類型作快速排序,分別用C標(biāo)準(zhǔn)庫(kù)中的qsort函數(shù)和STL中的排序算法。結(jié)果如圖6所示。
從圖中可以看到C標(biāo)準(zhǔn)庫(kù)和C++的STL排序算法之間性能有著顯著的差異。由于排序操作在C/C++編程中高頻出現(xiàn),上述測(cè)試結(jié)果是很有代表性的。
從本文前面的分析和性能測(cè)試可以看到,高層次抽象編程本身是相輔相成的。面向?qū)ο髾C(jī)制,如大型的繼承和運(yùn)行時(shí)多態(tài),往往會(huì)讓程序的性能下降。但是泛型機(jī)制,如模板和STL算法,總是趨向于彌補(bǔ)這一損失。因此,即使應(yīng)用程序的性能下降,高層次抽象也不應(yīng)該負(fù)主要責(zé)任。問(wèn)題是如何使用這語(yǔ)言讓其表現(xiàn)最佳。
有精心設(shè)計(jì)的庫(kù),程序員可以在一個(gè)比C或Fortran更高的水平抽象代碼。代碼將更容易閱讀,效率也可以得到保證。使用精心設(shè)計(jì)的特定應(yīng)用程序庫(kù),可以防止很多常見(jiàn)的錯(cuò)誤。具有相同函數(shù)的庫(kù)通常彼此有不同性能。所以選擇一個(gè)合適的庫(kù)也是提高程序性能的一種有效措施。一些庫(kù)之間有可能不同版本間存在差異,因此要注意選擇高效率的庫(kù)版本。
通常情況下,編譯優(yōu)化可以在很多層面上進(jìn)行,例如語(yǔ)句級(jí)、塊級(jí)和全局級(jí)別。優(yōu)化層次越高,程序性能提高越明顯。例如,在語(yǔ)句級(jí)優(yōu)化,編譯器可以很容易地保存臨時(shí)數(shù)據(jù)內(nèi)存,但在塊級(jí)別上,編譯器可以省略函數(shù)模板實(shí)例生成。抽象層次越高,越容易在更高的代碼級(jí)別形成一個(gè)清晰的結(jié)構(gòu),編譯器也更容易做更高層次的優(yōu)化。
應(yīng)根據(jù)應(yīng)用程序執(zhí)行環(huán)境進(jìn)行合理的編譯器優(yōu)化。通常來(lái)說(shuō),C++編譯器有很多不同的應(yīng)用程序參數(shù)來(lái)優(yōu)化配置選項(xiàng)。
一般來(lái)說(shuō),使用異常處理會(huì)降低系統(tǒng)的效率。在系統(tǒng)資源有限的情況下,我們應(yīng)該盡量不適用異常處理并禁止拋出異常。但是這樣對(duì)提高性能的作用有限,通常只有1%左右。更激進(jìn)的方法是禁用異常處理,但如果在這時(shí)拋出任何異常,系統(tǒng)都會(huì)立即崩潰。很多庫(kù)都依賴于異常處理,所以禁用異常處理是不安全的。
參數(shù)_declspec(novtable)是用于當(dāng)編譯器構(gòu)造特定對(duì)象時(shí)阻止初始化虛函數(shù)表的。因?yàn)槌橄箢愔械膶?shí)例無(wú)法獨(dú)立存在而是要依賴于具體的子類對(duì)象,不需要初始化虛函數(shù)列表,所以這個(gè)參數(shù)只對(duì)抽象類有用。由于虛函數(shù)的開(kāi)銷是很大的,當(dāng)系統(tǒng)資源有限時(shí)應(yīng)該盡量避免使用虛函數(shù)。如果必須使用,應(yīng)該禁止初始化虛函數(shù)表。
默認(rèn)情況下,編譯器只對(duì)防止代碼發(fā)生膨脹的函數(shù)進(jìn)行內(nèi)聯(lián)。使用/OB1可以迫使其打開(kāi)內(nèi)聯(lián)。但要優(yōu)化代碼執(zhí)行速度往往導(dǎo)致代碼膨脹,降低程序的時(shí)間和空間效率。因此建議不要強(qiáng)制打開(kāi)內(nèi)聯(lián)。
在分析了高層次抽象的主要機(jī)制后,人們知道高層次抽象是一把雙刃劍,它可以顯著改善編程效率和程序穩(wěn)定性,另一方面,如果不正確使用就會(huì)導(dǎo)致性能下降。這些操作會(huì)降低效率:對(duì)繼承的過(guò)度依賴,濫用虛函數(shù)或迭代器,強(qiáng)制大函數(shù)內(nèi)聯(lián),初始化抽象類的虛函數(shù)表,不禁用所有的異常處理函數(shù)或程序。可以提高效率的方案有:優(yōu)先使用庫(kù),選擇高效庫(kù),使用模板代替繼承,限制對(duì)嵌套類型參數(shù)的依賴,內(nèi)聯(lián)小的函數(shù),使用STL算法和函數(shù)對(duì)象。
圖6 500萬(wàn)個(gè)float和200萬(wàn)個(gè)strings的平均時(shí)間成本比較
[1] STROUSTRUP B.Abstraction,libraries,and efficiency in C++[J].Dr. Dobb’s Journal China,2003(1):10.
[2] STROUSTRUP B.The design and evolution of C++[M].New Jersey:Addison-Wesley,2002.
[3] DAN T,WISNIEWSKI R W,BACON D F,et al.Minimizing dependencies within generic classes for faster and smaller programs[J].Acm Sigplan Conference on Object Oriented Programming Systems Languages amp; Applications,2009(10):425-444.
[4] ISENSEE P.C++ optimization strategies and techniques[EB/OL].(2016-10-15)[2017-11-09].http://www.tantalon.com/pete/cppopt/main.htm.
[5] HOU J.Analysis of STL source code[D].Wuhan:Huazhong University of Science and Technology,2002.
[6] STROUSTRUP B.Learning standard C++ as a new language[J].C/C++ Users Journal,1999(5):43-54.
Analysis on efficiency of C++ high-level abstraction
Wang Wei1, Sun Xiaofan1, Yang Zhimin2
(1.Shandong Vocational College of Foreign Affairs Translation, Weihai 264504, China;2.Mechanial, Electrical and Information Engineering School, Shandong University, Weihai 264209, China)
At first, C ++ appears as an enhanced version of C, starting with adding classes, and C continues to add new features. It can be used as a stand-alone language when learning C++ because it does not depend on C language. Thinking in C++ thinks there is often a ± 5% difference in operational efficiency. There is argument that the high-level abstraction caused C++ efficiency decline. In order to verify this problem, this article summarizes the possible causes of the decline in efficiency and gives corresponding solutions based on the performance of encapsulation, inheritance and polymorphism in some representative cases and some comparison with C and Java.
C++; high-level abstraction; object-oriented; compiler optimization
王威(1981— ),女,遼寧沈陽(yáng)人,講師,學(xué)士;研究方向:信息技術(shù)應(yīng)用。