網(wǎng)站建設(shè)公司怎么宣傳廈門百度seo
C++元素的效率差異
- 類型轉(zhuǎn)換
- signed與unsigned轉(zhuǎn)換
- 整數(shù)大小轉(zhuǎn)換
- 浮點(diǎn)精度轉(zhuǎn)換
- 整數(shù)到浮點(diǎn)轉(zhuǎn)換
- 浮點(diǎn)到整數(shù)轉(zhuǎn)換
- 指針類型轉(zhuǎn)換
- 重新解釋對象的類型
- const_cast
- static_cast
- reinterpret_cast
- dynamic_cast
- 轉(zhuǎn)換類對象
類型轉(zhuǎn)換
在C++語法中,有幾種方式進(jìn)行類型轉(zhuǎn)換:
// Example 7.19
int i; float f;
f = i; // Implicit type conversion
f = (float)i; // C-style type casting
f = float(i); // Constructor-style type casting
f = static_cast<float>(i); // C++ casting operator
這些不同的方法有完全相同的效果。使用哪種方法是一個編程風(fēng)格的問題。下邊討論下不同轉(zhuǎn)換的時間損耗。
signed與unsigned轉(zhuǎn)換
。。。
有符號與無符號整數(shù)間的轉(zhuǎn)換只是讓編譯器以不同的方式解釋整數(shù)的比特。不檢查溢出,代碼不需要額外時間。
整數(shù)大小轉(zhuǎn)換
int i; short int s;
i = s;
一個整數(shù)轉(zhuǎn)換成一個位數(shù)更長的整數(shù)時,如果是有符號的,通過擴(kuò)展符號位,如果是無符號的,通過零擴(kuò)展。如果是一個算術(shù)表達(dá)式的結(jié)果進(jìn)行,通常需要1時鐘周期。如果從內(nèi)存讀取一個變量的值來轉(zhuǎn)換,通常不需要額外時間,如下:
。。。
將整數(shù)轉(zhuǎn)換到更小的類型僅僅是忽略高位比特,不檢查溢出。例如:
。。。
這個轉(zhuǎn)換不需要額外時間。它只是保存32位整數(shù)的低16位。
浮點(diǎn)精度轉(zhuǎn)換
在使用浮點(diǎn)寄存器棧時,float、double與long double間的轉(zhuǎn)換不需要額外時間。在使用XMM寄存器時,需要2到15時鐘周期(取決于處理器)。例子:
// Example 7.24
float a; double b;
a += b;
在這個例子中,如果使用XMM寄存器,轉(zhuǎn)換是相對低效的。a與b應(yīng)該是相同類型以避免。
整數(shù)到浮點(diǎn)轉(zhuǎn)換
有符號整數(shù)到float或double的轉(zhuǎn)換需要4 ~ 6時鐘周期,取決于處理器與使用的寄存器類型。無符號整數(shù)的轉(zhuǎn)換需要更長時間,除非AVX512指令集可用(AVX512DQ用于64bit無符號整數(shù))。如果沒有溢出的危險,首先把無符號整數(shù)轉(zhuǎn)換到有符號整數(shù)會更快的:
。。。
浮點(diǎn)到整數(shù)轉(zhuǎn)換
浮點(diǎn)值到整數(shù)的轉(zhuǎn)換需要非常長的時間,除非啟用SSE2或更新的指令集。通常,轉(zhuǎn)換需要50 ~ 100時鐘周期。原因是C/C++標(biāo)準(zhǔn)指定截斷,因此浮點(diǎn)取整模式必須改變?yōu)榻財?#xff0c;再改回來。
如果在代碼的關(guān)鍵部分存在浮點(diǎn)到整數(shù)轉(zhuǎn)換,那么對進(jìn)行優(yōu)化是重要的??赡艿姆桨赣?#xff1a;
- 使用不同類型的變量,避免轉(zhuǎn)換。
- 將中間結(jié)果保存為浮點(diǎn)類型,將轉(zhuǎn)換移出最里層循環(huán)。
。。。
指針類型轉(zhuǎn)換
指針可以被轉(zhuǎn)換到另一個類型的指針。類似的,指針可以轉(zhuǎn)換到整數(shù),或者整數(shù)可以轉(zhuǎn)換到指針。整數(shù)有足夠的bit位保存指針是重要的。
這些轉(zhuǎn)換不會產(chǎn)生額外的代碼。它只是以不同的方式解釋相同比特,或者繞過語法檢查。
當(dāng)然,這些轉(zhuǎn)換不安全。確保結(jié)果有效是程序員的責(zé)任。
重新解釋對象的類型
通過轉(zhuǎn)換地址類型,使編譯器將一個變量或?qū)ο螽?dāng)做另一個類型是可能的:
float x;
*(int*)&x |= 0x80000000; // Set sign bit of x
這里,語法看起來有些奇怪。x 的地址被類型轉(zhuǎn)換為一個整數(shù)指針,然后通過把x當(dāng)做整數(shù)訪問。實(shí)際上制作一個指針,編譯器不產(chǎn)生任何額外的代碼真正創(chuàng)造一個指針。這個指針只是被優(yōu)化掉,結(jié)果x被處理為一個整數(shù)。但 & 操作符強(qiáng)制編譯器在內(nèi)存而不是寄存器里保存x。上面例子通過使用只能應(yīng)用于整數(shù)的 | 操作符設(shè)置 x 的符號位。它比x = -abs( x );
更快。
在類型轉(zhuǎn)換指針時,要小心一些風(fēng)險:
- 違反嚴(yán)格的標(biāo)準(zhǔn)C別名規(guī)則,尤其是不同類型的兩個指針不能指向相同的對象(除了char指針)。優(yōu)化編譯器可能在兩個不同的寄存器中保存浮點(diǎn)與整數(shù)表示。你需要檢查編譯器的行為是否就是你所期望的。使用聯(lián)合更安全。
- 如果對象被當(dāng)做比其實(shí)際更大的類型對待,該技巧會無效。上面這個代碼將出錯,如果int比float使用更多比特。(在x86系統(tǒng)里,兩者都使用32比特)。
。。。
const_cast
const_cast用于去除一個指針的const限制。它有一些語法檢查,因此,比C風(fēng)格的類型轉(zhuǎn)換更安全,無需添加任何額外的代碼。例如:
。。。
static_cast
static_cast操作符做的與C形式的類型轉(zhuǎn)換相同。
reinterpret_cast
reinterpret_cast操作符用于指針轉(zhuǎn)換。與c風(fēng)格的轉(zhuǎn)換類似,但會進(jìn)行一些語法檢查,不產(chǎn)生任何額外的代碼。
dynamic_cast
dynamic_cast操作符用于將一個類指針轉(zhuǎn)換為另一個類的指針。它對轉(zhuǎn)換的有效性進(jìn)行運(yùn)行時檢查。例如,在一個基類指針被轉(zhuǎn)換為派生類的指針時,它檢查原始指針是否真的指向派生類的一個對象。這個檢查使得dynamic_cast比簡單的類型轉(zhuǎn)換更耗時些,但也更安全。它可能捕捉到原本沒發(fā)現(xiàn)的編程錯誤。
轉(zhuǎn)換類對象
涉及類對象的轉(zhuǎn)換(而不是對象指針)是看可能的,只要程序員定義了說明如何進(jìn)行這個轉(zhuǎn)換的一個構(gòu)造函數(shù)、一個重載賦值操作符或一個重載類型轉(zhuǎn)換操作符。構(gòu)造函數(shù)或重載操作符與成員函數(shù)效率相同。
歡迎交流