溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

C++代碼操作的效率有哪些

發(fā)布時(shí)間:2021-10-18 17:34:30 來(lái)源:億速云 閱讀:115 作者:iii 欄目:web開(kāi)發(fā)

這篇文章主要講解了“C++代碼操作的效率有哪些”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“C++代碼操作的效率有哪些”吧!

本專題將分析C++各種代碼操作的效率,包括不同類型變量的存儲(chǔ)效率,使用智能指針、循環(huán)、函數(shù)參數(shù)、虛函數(shù)、數(shù)組等的效率,以及如何做針對(duì)性優(yōu)化,或選擇更有效的替代方案。

詳細(xì)目錄看下圖:

C++代碼操作的效率有哪些

變量存儲(chǔ)區(qū)域:

在C++中,變量存儲(chǔ)在哪類內(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)銷的,如果我們想避免這類開(kāi)銷,難道就要聲明為全局變量了嗎?其實(shí)我們也可將變量存儲(chǔ)在類對(duì)象中,多個(gè)函數(shù)都訪問(wèn)類對(duì)象中的變量成員。

某些情況下,可以考慮static和const共用,例如聲明一個(gè)靜態(tài)常量查詢表:

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)銷也較大。盡量避免動(dòng)態(tài)分配內(nèi)存吧,或者用JeMalloc替換一波?或內(nèi)存池?

整數(shù)變量和運(yùn)算

整型大小

整數(shù)中,不同類型可能會(huì)有不同的大小,下圖總結(jié)了不同整型的大小和最大最小值:

C++代碼操作的效率有哪些

在不同的平臺(tái),聲明特定大小整數(shù)的方法不同,我們可以使用標(biāo)準(zhǔn)頭文件stdint.h,聲明特定大小的整型,該方法還可以跨平臺(tái),可移植。

大多數(shù)情況下,整數(shù)運(yùn)算非常快,但是,如果整數(shù)大于可用寄存器大小,效率就會(huì)低一些。例如,在32位系統(tǒng)中,使用64位整數(shù)效率低一些,特別是用于乘法或除法時(shí)。

如果聲明了int類型,但是沒(méi)有指定具體大小,編譯器將始終選擇最有效的整數(shù)大小。較小大小的整數(shù)如char、short  int等,效率可能稍微低一些,在很多情況下,編譯器在進(jìn)行計(jì)算時(shí),會(huì)將這些類型轉(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)算類似。

對(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)銷。這只不過(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,有兩種不同類型的浮點(diǎn)寄存器,對(duì)應(yīng)不同類型的浮點(diǎn)指令,每種類型都有優(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)算。很少有編譯器可以混合兩種不同類型的浮點(diǎn)運(yùn)算,不能為每次運(yùn)算選擇最優(yōu)類型。大多數(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)生布爾輸出的值,則可以優(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ì)算超出了有效地址的范圍,或者指針類型轉(zhuǎn)換為錯(cuò)誤的類型,那么指針可能是無(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)行尋址。同樣的,類中聲明的所有非靜態(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í)鐘周期的延遲。

智能指針

智能指針是一種行為與指針類似的對(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)銷更大一些。選擇智能指針時(shí)可以更多的選擇unique_ptr,編譯器可以做優(yōu)化,能夠在簡(jiǎn)單情況下剝離掉unique_ptr的大部分或者全部開(kāi)銷,這樣效率就和直接使用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)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

c++
AI