這篇文章主要講解了“C++代碼操作的效率有哪些”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“C++代碼操作的效率有哪些”吧!
岳池ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場(chǎng)景,ssl證書(shū)未來(lái)市場(chǎng)廣闊!成為創(chuàng)新互聯(lián)公司的ssl證書(shū)銷(xiāo)售渠道,可以享受市場(chǎng)價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話(huà)聯(lián)系或者加微信:13518219792(備注:SSL證書(shū)合作)期待與您的合作!
本專(zhuān)題將分析C++各種代碼操作的效率,包括不同類(lèi)型變量的存儲(chǔ)效率,使用智能指針、循環(huán)、函數(shù)參數(shù)、虛函數(shù)、數(shù)組等的效率,以及如何做針對(duì)性?xún)?yōu)化,或選擇更有效的替代方案。
詳細(xì)目錄看下圖:
變量存儲(chǔ)區(qū)域:
在C++中,變量存儲(chǔ)在哪類(lèi)內(nèi)存,取決于開(kāi)發(fā)者聲明它們的方式。如果數(shù)據(jù)不連續(xù),分成無(wú)數(shù)段分散在內(nèi)存中,會(huì)降低數(shù)據(jù)的Cache命中率。因此,理解變量如何存儲(chǔ)非常重要。
??臻g
??臻g,通常用于存儲(chǔ)局部變量、函數(shù)參數(shù)、函數(shù)返回地址、函數(shù)返回前需要恢復(fù)的寄存器等。每次調(diào)用函數(shù)時(shí),系統(tǒng)都會(huì)分配一段??臻g,用于存儲(chǔ)這些東西,函數(shù)返回時(shí),這段??臻g會(huì)被回收,下次調(diào)用函數(shù)時(shí),程序還可以重用這段棧空間。
一般來(lái)說(shuō),程序每個(gè)線程有固定大小的??臻g,使用多少,回收多少,只是偏移量偏移多少的問(wèn)題。??臻g特別高效是因?yàn)橥欢蝺?nèi)存空間可以被反復(fù)使用,內(nèi)存很容易就加載到Cache中,Cache命中率更高。
我們可以多利用棧空間。所有的變量,最好都在使用它們的函數(shù)中聲明。有些情況下可以在大括號(hào){ }內(nèi)聲明變量,盡可能縮小變量的作用域。
全局或靜態(tài)空間
全局變量,任何函數(shù)都可以訪問(wèn),存儲(chǔ)在內(nèi)存的靜態(tài)空間中。static關(guān)鍵字聲明的變量、浮點(diǎn)常量、字符串常量、虛函數(shù)表等,都存儲(chǔ)在靜態(tài)空間中。
靜態(tài)空間的優(yōu)點(diǎn)是,可以在程序啟動(dòng)前就將其初始化為所需的值。缺點(diǎn)是,即使變量只使用一次,或者只在程序的一小部分中使用,它的內(nèi)存,也會(huì)在程序整個(gè)運(yùn)行過(guò)程中被占用,會(huì)降低Cache的效率。
盡量不要將變量聲明為全局變量,一個(gè)變量如果被多個(gè)函數(shù)使用,可以考慮將其作為參數(shù),但是參數(shù)傳遞是有開(kāi)銷(xiāo)的,如果我們想避免這類(lèi)開(kāi)銷(xiāo),難道就要聲明為全局變量了嗎?其實(shí)我們也可將變量存儲(chǔ)在類(lèi)對(duì)象中,多個(gè)函數(shù)都訪問(wèn)類(lèi)對(duì)象中的變量成員。
某些情況下,可以考慮static和const共用,例如聲明一個(gè)靜態(tài)常量查詢(xún)表:
float SomeFunction(int x) { static const float list[] = {1.1, 2.2, 3.4, 4.4, 5.5}; return list[x]; }
這種方式的好處是,不需要在每次調(diào)用函數(shù)時(shí)對(duì)列表進(jìn)行初始化。static聲明意味著在第一次調(diào)用初始化后,后續(xù)就不再需要初始化,但這樣效率較低,因?yàn)樾枰~外檢查它是第一次調(diào)用,還是已經(jīng)被調(diào)用過(guò)。加入const聲明,可以告訴編譯器,不需要對(duì)是否是第一次調(diào)用來(lái)進(jìn)行檢查。所以最好加上static和const聲明,以便讓編譯器更好的優(yōu)化。
字符串常量和浮點(diǎn)數(shù)常量,也經(jīng)常保存在靜態(tài)空間中,例如:
a = b * 3.5; c = d + 3.5;
這里,常數(shù)3.5將存儲(chǔ)在靜態(tài)空間中,大多數(shù)編譯器會(huì)識(shí)別出這兩個(gè)常量是相同的,因此只需要存儲(chǔ)一份常量。整個(gè)程序中所有相同的常量將被連接在一起,優(yōu)化程序中常量的占用空間。
寄存器存儲(chǔ)
寄存器是CPU中的一小塊內(nèi)存,用作臨時(shí)存儲(chǔ)。訪問(wèn)寄存器中的變量速度非常快,但是寄存器數(shù)量有限,存儲(chǔ)的變量也有限。編譯器優(yōu)化時(shí),會(huì)自動(dòng)選擇函數(shù)中的最常用變量,存到寄存器中。程序中的局部變量就很適合于存儲(chǔ)在寄存器中。
寄存器數(shù)量有限,32位X86系統(tǒng)中,大約有6個(gè)整數(shù)寄存器用于通用目的,64位系統(tǒng)中有14個(gè)。而浮點(diǎn)變量使用不同的寄存器,32位系統(tǒng)中大約有8個(gè)可用的浮點(diǎn)寄存器,64位系統(tǒng)中有16個(gè),當(dāng)在64位系統(tǒng)中啟用更高級(jí)的指令集時(shí),可能會(huì)有更多可用的浮點(diǎn)寄存器。
volatile
這里需要特別關(guān)注下volatile關(guān)鍵字,該關(guān)鍵字表示其修飾的變量可以被另一個(gè)線程更改,防止編譯器做一些過(guò)度優(yōu)化。例如:
volatile int seconds; void DelayFiveSeconds() { seconds = 0; while (seconds < 5) { // do nothing while seconds count to 5 } }
在本例中,DelayFiveSeconds()將一直等待,直到另一個(gè)線程將seconds增加到5。
如果seconds沒(méi)被聲明為volatile,那么編譯器可能會(huì)進(jìn)行過(guò)度優(yōu)化,將假定在while循環(huán)中seconds保持為0,循環(huán)內(nèi)的任何內(nèi)容都不能更改該值。循環(huán)將是while(0 < 5){},這將是個(gè)死循環(huán)。
關(guān)鍵字volatile的作用是,確保變量永遠(yuǎn)存儲(chǔ)在內(nèi)存中,而不是在寄存器中,并阻止對(duì)變量的所有優(yōu)化。
注意volatile不保證原子性,它不會(huì)阻止兩個(gè)線程同時(shí)嘗試寫(xiě)操作。其他線程增加seconds的同時(shí),試圖將seconds設(shè)置為0,這樣可能會(huì)失敗。更安全的做法是,一個(gè)線程只讀取seconds,并等待該值更改。
thread-local存儲(chǔ)
C++11中可以使用thread_local關(guān)鍵字來(lái)聲明線程本地變量,C++11前也有別的方式聲明,被修飾的變量對(duì)于每個(gè)線程都有一份拷貝,保證了線程安全。thread-local存儲(chǔ)效率較低,因?yàn)樗峭ㄟ^(guò)全局指針訪問(wèn)。我們應(yīng)該盡量避免線程本地存儲(chǔ),可以更多將變量存儲(chǔ)在線程自己的棧中,即在線程自己的函數(shù)中聲明變量。
堆內(nèi)存
堆內(nèi)存主要通過(guò)操作符new和delete動(dòng)態(tài)分配,或者使用函數(shù)malloc和free。如果以隨機(jī)的順序分配和釋放不同大小的內(nèi)存,很容易產(chǎn)生內(nèi)存碎片,分散在堆內(nèi)存的不同地方,而且頻繁分配內(nèi)存,開(kāi)銷(xiāo)也較大。盡量避免動(dòng)態(tài)分配內(nèi)存吧,或者用JeMalloc替換一波?或內(nèi)存池?
整數(shù)變量和運(yùn)算
整型大小
整數(shù)中,不同類(lèi)型可能會(huì)有不同的大小,下圖總結(jié)了不同整型的大小和最大最小值:
在不同的平臺(tái),聲明特定大小整數(shù)的方法不同,我們可以使用標(biāo)準(zhǔn)頭文件stdint.h,聲明特定大小的整型,該方法還可以跨平臺(tái),可移植。
大多數(shù)情況下,整數(shù)運(yùn)算非???,但是,如果整數(shù)大于可用寄存器大小,效率就會(huì)低一些。例如,在32位系統(tǒng)中,使用64位整數(shù)效率低一些,特別是用于乘法或除法時(shí)。
如果聲明了int類(lèi)型,但是沒(méi)有指定具體大小,編譯器將始終選擇最有效的整數(shù)大小。較小大小的整數(shù)如char、short int等,效率可能稍微低一些,在很多情況下,編譯器在進(jìn)行計(jì)算時(shí),會(huì)將這些類(lèi)型轉(zhuǎn)換為默認(rèn)大小的整數(shù),然后只使用結(jié)果中的低8位或者低16位。在64位系統(tǒng)中,只要我們不做除法,使用32位整數(shù)和64位整數(shù)的效率其實(shí)沒(méi)多大差別。
整數(shù)運(yùn)算時(shí),我們需要考慮中間計(jì)算的結(jié)果,看是否會(huì)導(dǎo)致溢出。例如表達(dá)式a=b+c+d,即使b、c、d都低于整數(shù)最大值,但是可能b+c就會(huì)導(dǎo)致整數(shù)溢出,我們需要時(shí)刻注意。
有符號(hào)整數(shù)和無(wú)符號(hào)整數(shù)
多數(shù)情況下,使用有符號(hào)整數(shù)和無(wú)符號(hào)整數(shù),在速度上沒(méi)有區(qū)別,但有一些特殊情況:
常量除法,當(dāng)除以常量時(shí),無(wú)符號(hào)整數(shù)比有符號(hào)整數(shù)效率更高,模運(yùn)算類(lèi)似。
對(duì)于大多數(shù)指令集,使用有符號(hào)整數(shù)到浮點(diǎn)數(shù)的轉(zhuǎn)換,要比使用無(wú)符號(hào)整數(shù)轉(zhuǎn)換更快。
有符號(hào)和無(wú)符號(hào)整數(shù)的溢出行為不同:無(wú)符號(hào)整數(shù)的溢出產(chǎn)生一個(gè)低正結(jié)果,有符號(hào)整數(shù)的溢出是官方未定義的。有符號(hào)整數(shù),正常的行為是將正溢出轉(zhuǎn)換為負(fù)值,但是編譯器可能做一些優(yōu)化,它會(huì)假設(shè)不會(huì)發(fā)生溢出。
有符號(hào)整數(shù)和無(wú)符號(hào)整數(shù)之間的轉(zhuǎn)換,沒(méi)有任何開(kāi)銷(xiāo)。這只不過(guò)是對(duì)同一符號(hào)位的不同解釋而已。負(fù)整數(shù)在轉(zhuǎn)換為無(wú)符號(hào)時(shí),將被解釋為一個(gè)非常大的正數(shù)。
int a, b; double c; b = (unsigned int)a / 10; // 轉(zhuǎn)換成無(wú)符號(hào)整數(shù)做除法更快 c = a * 2.5; // 有符號(hào)整數(shù)隱式轉(zhuǎn)換為double型
在上例中,將a轉(zhuǎn)換為unsigned,可以使除法更快。當(dāng)然,只有當(dāng)a絕對(duì)不會(huì)是負(fù)數(shù)的時(shí)候,才可以這么轉(zhuǎn)換。最后一行,在與常數(shù)2.5相乘之前,會(huì)隱式地將a轉(zhuǎn)換為double,因?yàn)楹笳呤莇ouble,這里a作為有符號(hào)整數(shù)去轉(zhuǎn)換,效率更高。
注意,在進(jìn)行比較操作時(shí),例如<操作,不要混用有符號(hào)整數(shù)和無(wú)符號(hào)整數(shù)。有符號(hào)整數(shù)和無(wú)符號(hào)整數(shù)的比較,可能會(huì)產(chǎn)生意想不到的結(jié)果。
整數(shù)運(yùn)算
整數(shù)運(yùn)算通常非??臁:?jiǎn)單的整數(shù)運(yùn)算,如加法、減法、比較、位運(yùn)算等,在大多數(shù)微處理器上只需要一個(gè)時(shí)鐘周期。乘法和除法需要更長(zhǎng)的時(shí)間。整數(shù)乘法在奔騰4CPU上需要11個(gè)時(shí)鐘周期,大多數(shù)情況乘法都需要3 - 4個(gè)時(shí)鐘周期,整數(shù)除法需要40 - 80個(gè)時(shí)鐘周期,具體取決于CPU。
自增和自減運(yùn)算
++i和i++速度一樣快,當(dāng)僅用于遞增變量時(shí),使用++i和i++沒(méi)有任何區(qū)別,效果完全相同,例如:
for(i=0;i
浮點(diǎn)數(shù)及其運(yùn)算
現(xiàn)代x86家族的CPU,有兩種不同類(lèi)型的浮點(diǎn)寄存器,對(duì)應(yīng)不同類(lèi)型的浮點(diǎn)指令,每種類(lèi)型都有優(yōu)缺點(diǎn)。
x87寄存器
x87寄存器是浮點(diǎn)運(yùn)算的傳統(tǒng)方法,這些寄存器都有長(zhǎng)雙精度,多個(gè)寄存器組成了一組寄存器棧,使用寄存器棧的優(yōu)點(diǎn)有:
所有的計(jì)算都是用雙精度完成的不同精度之間的轉(zhuǎn)換不需要額外的時(shí)間。
對(duì)于數(shù)學(xué)函數(shù),如對(duì)數(shù)函數(shù)和三角函數(shù),有一些內(nèi)置的指令。
代碼很緊湊,在代碼緩存中占用的空間很小。
寄存器棧也有缺點(diǎn):
由于寄存器棧的組織方式,編譯器很難創(chuàng)建寄存器變量。
浮點(diǎn)數(shù)比較速度很慢,除非啟用更高的指令集。
當(dāng)使用雙精度時(shí),除法、平方根和數(shù)學(xué)函數(shù),需要更多的時(shí)間來(lái)計(jì)算。
向量寄存器
也叫矢量寄存器,有XMM、YMM或ZMM等寄存器,是進(jìn)行浮點(diǎn)運(yùn)算的一種較新的方法,浮點(diǎn)運(yùn)算以單精度或雙精度完成,中間結(jié)果的計(jì)算精度始終與操作數(shù)相同,使用向量寄存器的優(yōu)點(diǎn)有:
制作浮點(diǎn)寄存器變量很容易。
向量操作可用于對(duì)向量寄存器中的多個(gè)變量進(jìn)行并行計(jì)算。
它也有缺點(diǎn):
不支持長(zhǎng)雙精度。
混合不同精度的表達(dá)式計(jì)算,需要精度轉(zhuǎn)換指令,這可能非常耗時(shí)。
數(shù)學(xué)函數(shù)必須使用函數(shù)庫(kù),但這通常也比內(nèi)置的硬件函數(shù)快。
在幾乎所有具有浮點(diǎn)運(yùn)算能力的系統(tǒng)中,都可以使用x87浮點(diǎn)寄存器,而XMM、YMM和ZMM寄存器分別需要SSE、AVX和AVX512指令集。
現(xiàn)代編譯器,更多情況下會(huì)使用向量寄存器,來(lái)進(jìn)行浮點(diǎn)運(yùn)算。很少有編譯器可以混合兩種不同類(lèi)型的浮點(diǎn)運(yùn)算,不能為每次運(yùn)算選擇最優(yōu)類(lèi)型。大多數(shù)情況下,當(dāng)沒(méi)有使用向量運(yùn)算時(shí),單精度浮點(diǎn)數(shù)運(yùn)算和雙精度浮點(diǎn)數(shù)運(yùn)算速度大體相同,無(wú)論精度如何,加法、減法、乘法等運(yùn)算的速度都是相同的。但如果開(kāi)啟向量運(yùn)算,使用XMM等向量寄存器時(shí),單精度除法、平方根和數(shù)學(xué)函數(shù)的計(jì)算速度要比雙精度快。
如果真的對(duì)精度有高要求,可以使用雙精度浮點(diǎn)數(shù),不需要太擔(dān)心速度。但如果我們可以利用好向量運(yùn)算,或者有個(gè)大的浮點(diǎn)數(shù)數(shù)組,想要充分利用Cache,那可以考慮使用單精度浮點(diǎn)數(shù)。
浮點(diǎn)加法需要3 - 6個(gè)時(shí)鐘周期,乘法操作需要4 - 8個(gè)時(shí)鐘周期,除法需要14 - 45個(gè)時(shí)鐘周期,這取決于CPU。當(dāng)使用傳統(tǒng)的x87浮點(diǎn)寄存器時(shí),浮點(diǎn)數(shù)比較操作,和浮點(diǎn)數(shù)到整數(shù)的轉(zhuǎn)換操作,效率較低。
注意:
同一個(gè)表達(dá)式中,不要混合使用單精度和雙精度浮點(diǎn)數(shù)。
盡量避免整型和浮點(diǎn)型的轉(zhuǎn)換。
向量寄存器支持多種模式,可以根據(jù)實(shí)際需要設(shè)置不同的模式,例如flush-to-zero模式、denormals-are-zero模式等。
枚舉
枚舉其實(shí)就是個(gè)偽裝的整數(shù),它的效率與整數(shù)相同。注意,枚舉值名字可能與一些變量或函數(shù)的名字發(fā)生沖突,可以將頭文件中的枚舉設(shè)置成較長(zhǎng)且唯一的名字,或者放入命名空間,也可以使用enum class聲明枚舉。
布爾
布爾操作的順序優(yōu)化
布爾操作符&&和||的操作數(shù)按以下方式計(jì)算。如果&&的第一個(gè)操作數(shù)為false,則根本不計(jì)算第二個(gè)操作數(shù),因?yàn)闊o(wú)論第二個(gè)操作數(shù)的值是多少,結(jié)果都是false。同樣,如果||的第一個(gè)操作數(shù)為true,則不計(jì)算第二個(gè)操作數(shù),因?yàn)榻Y(jié)果肯定是true。
所以,我們可以將通常為true的操作數(shù)放在&&表達(dá)式的最后,或放在||表達(dá)式的最開(kāi)始。例如,假設(shè)a在50%的情況下為真,b在10%的情況下為真。當(dāng)a為真時(shí),表達(dá)式a && b需要計(jì)算b,這是50%的情況。等價(jià)的表達(dá)式b && a只需要在b為真時(shí)計(jì)算a,這只占10%的時(shí)間。
如果一個(gè)操作數(shù)比另一個(gè)操作數(shù)更可預(yù)測(cè),那么將最可預(yù)測(cè)的操作數(shù)放在前面。
如果一個(gè)操作數(shù)比另一個(gè)操作數(shù)計(jì)算得快,那么將計(jì)算得最快的操作數(shù)放在前面。
但是,在改變布爾操作數(shù)的順序必須要小心:如果操作數(shù)的計(jì)算有副作用,如果第一個(gè)操作數(shù)被用來(lái)確定第二個(gè)操作數(shù)是否有效,則不能交換操作數(shù)。例如:
unsigned int i; const int ARRAYSIZE = 100; float list[ARRAYSIZE]; if (i < ARRAYSIZE && list[i] > 3) {...}
這里我們不能交換順序,因?yàn)楫?dāng)i>ARRAYSIZE時(shí),list[i]操作是非法的,另一個(gè)例子:
if (handle != INVALID_HANDLE_VALUE && WriteFile(handle, ...)) {...}
同樣,這里我們也不可能交換順序。
布爾值
布爾變量被存儲(chǔ)為8位整數(shù),值為0表示false, 1表示true。此種意義上,布爾變量由多種因素確定,即所有以布爾變量作為輸入的操作符,有可能不只是0和1,而以布爾變量作為輸出的操作符,只能產(chǎn)出0或1的值。這樣可能布爾變量作為輸入的操作效率較低。
舉例來(lái)說(shuō),對(duì)于
bool a, b, c, d; c = a && b; d = a || b;
而編譯器可能是這么實(shí)現(xiàn)的:
bool a, b, c, d; if (a != 0) { if (b != 0) { c = 1; } else { goto cfalse; } } else { cfalse: c = 0; } if (a == 0) { if (b == 0) { d = 0; } else { goto dtrue; } } else { dtrue: d = 1; }
當(dāng)然,這不是最優(yōu)方式。在錯(cuò)誤預(yù)測(cè)的情況下,分支可能還需要很長(zhǎng)時(shí)間。如果可以確定操作數(shù)除了0和1之外,沒(méi)有其他值,那么布爾操作的效率會(huì)高得多。編譯器沒(méi)有做這樣的假設(shè)的原因是,如果變量沒(méi)有初始化,或者來(lái)源未知,那么它們可能有其它的值。如果a和b已經(jīng)初始化為有效值,或者它們來(lái)自產(chǎn)生布爾輸出的值,則可以?xún)?yōu)化上述代碼。優(yōu)化后的代碼如下所示:
char a = 0, b = 0, c, d; c = a & b; d = a | b;
這里,我們可以使用char(或int)代替bool,以便能夠使用位操作符(&和|)而不是布爾操作符(&&和||)。按位操作符,是只占用一個(gè)時(shí)鐘周期的單個(gè)指令。即使a和b的值不是0或1,OR操作符(|)也可以工作。但如果操作數(shù)的值不是0和1,則AND操作符(&)和異或操作符(^)可能會(huì)產(chǎn)生不一致的結(jié)果。
注意這里有個(gè)坑,我們不能使用~代替!,相反,如果確定輸入是0或1,可以通過(guò)與1做異或來(lái)得到!的值。
舉例:
bool a, b; b = !a;
可以被優(yōu)化成:
char a = 0, b; b = a ^ 1;
指針和引用
看代碼:
void FuncA(int *p) { *p = *p + 2; } void FuncB(int &r) { r = r + 2; }
這兩段分別使用指針和引用的代碼,它們實(shí)際上做的是相同的事情,具體我們可以看它們編譯后生成的代碼,其實(shí)它們的匯編代碼完全相同,區(qū)別僅僅是編程風(fēng)格的問(wèn)題。
指針優(yōu)于引用的理由是:
直接看上面的函數(shù)體,很明顯看出p是一個(gè)指針,但不清楚r是一個(gè)引用,還是一個(gè)簡(jiǎn)單的變量,使用指針讓閱讀代碼的人更清楚地知道發(fā)生了什么。
指針的指向可以更改,使用更靈活,還可以用指針做算術(shù)運(yùn)算。
引用優(yōu)于指針的理由是:
引用比指針更安全,因?yàn)樵诖蠖鄶?shù)情況下,引用肯定指向一個(gè)有效的地址,而且引用的指向不可更改。而對(duì)于指針,如果沒(méi)有初始化,那指針?biāo)阈g(shù)計(jì)算超出了有效地址的范圍,或者指針類(lèi)型轉(zhuǎn)換為錯(cuò)誤的類(lèi)型,那么指針可能是無(wú)效的,并導(dǎo)致致命錯(cuò)誤。
引用對(duì)于復(fù)制構(gòu)造函數(shù)和重載運(yùn)算符很有用。
聲明為常量引用的函數(shù)形參,可接受表達(dá)式作為實(shí)參,而指針和非常量引用需要變量。
使用指針或引用訪問(wèn)變量,可能與直接訪問(wèn)一樣快。函數(shù)中聲明的所有非靜態(tài)變量,都存儲(chǔ)在棧上,實(shí)際上它們也是通過(guò)棧指針進(jìn)行尋址。同樣的,類(lèi)中聲明的所有非靜態(tài)變量,也是通過(guò)隱式的this指針訪問(wèn),所以,大多數(shù)變量實(shí)際上都是通過(guò)指針訪問(wèn)。
使用指針或引用也有缺點(diǎn),它需要一個(gè)額外的寄存器來(lái)保存指針或引用的值,而寄存器是一種稀缺資源,特別是在32位模式下。如果寄存器數(shù)量不足,那么每次使用指針時(shí)都必須從內(nèi)存中加載,速度就會(huì)變慢。
注意指針這里有個(gè)坑:即指針的算數(shù)運(yùn)算:
struct A { int a; int b; }; A *a; a = ++a; a = ++(char*)a;
++a和++(void*)a,它們的運(yùn)算結(jié)果是不同的,++a里其實(shí)加的值是8,因?yàn)锳大小是8,++(void*)a里其實(shí)加的值是1,因?yàn)?char)大小是1。
函數(shù)指針
如果目標(biāo)地址可以預(yù)測(cè),通過(guò)函數(shù)指針調(diào)用函數(shù),相比于直接調(diào)用函數(shù),要多花幾個(gè)時(shí)鐘周期。如果函數(shù)指針的值,與上次執(zhí)行語(yǔ)句時(shí)相同,則目標(biāo)地址會(huì)被預(yù)測(cè)成功,而如果函數(shù)指針的值發(fā)生變化,目標(biāo)地址很可能會(huì)被錯(cuò)誤預(yù)測(cè),預(yù)測(cè)失敗會(huì)導(dǎo)致有多個(gè)時(shí)鐘周期的延遲。
智能指針
智能指針是一種行為與指針類(lèi)似的對(duì)象。C++11后基本上有兩種智能指針,unique_ptr和shared_ptr,unique_ptr的特點(diǎn)是有且只有一個(gè)指針擁有所分配的對(duì)象,只有一個(gè)對(duì)象指針擁有對(duì)象的所有權(quán),而shared_ptr的特點(diǎn)是可以有多個(gè)指針共同指向同一個(gè)對(duì)象,顯然shared_ptr比unique_ptr的開(kāi)銷(xiāo)更大一些。選擇智能指針時(shí)可以更多的選擇unique_ptr,編譯器可以做優(yōu)化,能夠在簡(jiǎn)單情況下剝離掉unique_ptr的大部分或者全部開(kāi)銷(xiāo),這樣效率就和直接使用new和delete基本相同。一般一個(gè)函數(shù)內(nèi)new,需要另一個(gè)函數(shù)內(nèi)delete的場(chǎng)景下,可以考慮使用智能指針。但如果在同一個(gè)函數(shù)內(nèi)new和delete,且函數(shù)體沒(méi)有過(guò)多的分支,或許就不需要使用智能指針啦。
感謝各位的閱讀,以上就是“C++代碼操作的效率有哪些”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)C++代碼操作的效率有哪些這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
當(dāng)前文章:C++代碼操作的效率有哪些
網(wǎng)站地址:http://jinyejixie.com/article46/gpsshg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁(yè)設(shè)計(jì)公司、微信小程序、做網(wǎng)站、搜索引擎優(yōu)化、外貿(mào)網(wǎng)站建設(shè)、企業(yè)網(wǎng)站制作
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)