提高C 效能的程式設計技術

2021-10-08 20:45:56 字數 4048 閱讀 1573

當乙個物件確實被需要的時候才建立它。

物件的建立(或銷毀)觸發對父物件和成員物件的遞迴建立(銷毀)。要當心複雜層次中物件的復合使用。它們使得建立和銷毀的開銷更為高昂。

初始化成員變數使用顯式構造。

class

ftest

private

: std::wstring _str;

};

只能在執行期間解析的虛函式是不允許使用內聯的。因為函式呼叫的動態繫結是繼承的結果。所以消除動態繫結的一種方法是使用基於模板的設計來替代繼承。模板把解析的步驟從執行期間提前到了編譯期間

預備類

class

locker

virtual

~locker()

virtual

void

lock()

=0;virtual

void

unlock()

=0;}

;class

cirticalsectionlocker

:public locker

~cirticalsectionlocker()

virtual

void

lock

()override

virtual

void

unlock

()override }

;class

mutexlocker

:public locker

~mutexlocker()

virtual

void

lock

()override

virtual

void

unlock

()override }

;class

semaphorelocker

:public locker

~semaphorelocker()

virtual

void

lock

()override

virtual

void

unlock

()override }

;

在派生自string類的基礎上,以如下三個角度來設計

示例**,只是輔助理解,不一定能夠編譯通過

硬編碼

從string類中派生出 criticalsectionstring,mutexstring和semahorestrintg。每個類實現各自的同步機制。

class

mutexstring

:public std::string

private

:mutexlocker _mutexlocker;

}

此種設計在效能上具有優勢。通過虛函式來呼叫正確的lock以及unlock方法。但是此設計的不足之處在於需要為每種同步機制編寫各自的string類。導致**重用性較低

繼承

派生出乙個單獨的threadsafestring類。它包含指向locker物件的指標,在執行期間通過多型機制選擇特定的同步機制。

class

threadsafestring

:public string

intgetlength()

private

: locker* _locker;

}

虛函式呼叫lock以及unlock僅在執行期間解析,因此不能對它們內聯。從而帶來了效能的損失。

模板

基於模板的string類,該類由locker型別引數化後得到

template

<

class

locker

>

class

threadsafestring

:public string

intgetlength()

;private

: locker _locker;};

template

<

class

locker

>

inline

int threadsafestring

::getlength()

這種設計也避免了對lock以及unlock的虛函式呼叫。threadsafestring宣告在例項化模板時選擇特定的同步型別。如同硬編碼一樣,它使編譯器可以解析這兩個虛函式呼叫並且內聯。

模板計算從執行期間提前到編譯期間來做,並且在編譯時使用內聯,因此提高了效能。

如果必須按照值返回物件,通過rvo可以省略建立和銷毀區域性物件的步驟,從而改善效能

class

test

~test()

};void

functionpassvalue

(test test)

//此種方式 編譯器將建立乙個test型別的臨時物件。並且使用test作為輸入引數來複製構造它(臨時物件)。然後臨時物件作為實參傳遞給functionpassvalue 該新建立的臨時物件將按引用方式傳遞給functionpassvalue

void

functionpassreferences

(test &test)

void

functionpasspointer

(test *test)

//按照指標以及引用方式不會產生臨時物件。

建立和銷毀臨時物件的代價是比較高的。倘若可以,應該按指標或者引用來傳遞物件以避免生成臨時物件

如果編寫的函式是按值返回物件(與引用或者指標相對),就很可能產生臨時物件。

std::wstring getwstringbyreturnvalue()

//編譯器生成乙個臨時物件來儲存返回值

關於 std::string的 + 運算子

std::string s1 =

"hello"

;std::string s2 =

"world"

;std::string s3;

s3 = s1 + s2;

//產生乙個臨時物件

std::string s3 = s1+s2;

//不會產生臨時物件

為什麼產生臨時物件

因為我們沒有權利修改s3的舊內容並使用 s1+s2的新內容來覆蓋它。賦值運算

符(=)負責把 s3 由舊內容變為新內容。然而編譯器不允許跳過std::string::operator=(),因此必須生成臨時物件。但如果s3是沒有舊內容的新物件呢?在這種情況下,就無須擔心舊內容。此時編譯器可以使用s3而不是臨時物件來儲存。s1+s2的結果直接複製構造至s3物件中。s3取代了不再必須的臨時物件

臨時物件會以建構函式和析構函式的形式降低一半的效能。

將建構函式宣告為 explicit ,可以組織編譯器在幕後使用型別轉換

編譯器常常建立臨時物件來解決型別不匹配問題。通過函式過載可以避免這種情況

如果可能, 應該盡量避免使用物件拷貝(函式返回按值返回,函式實參為值傳遞)。按引用傳遞和返回物件

在 operator 可能是 "+、-、*「或者」/"的地方。使用 operator=運算子可以消除臨時物件

固定大小

分配固定大小記憶體的記憶體管理器

可變大小

分配任意大小記憶體塊的記憶體管理器。所請求分配的大小事是未知的。

單執行緒

記憶體管理器侷限在乙個單執行緒內。記憶體被乙個執行緒使用,並且不越出該執行緒的界限。這種記憶體管理器不設涉及相互訪問的多執行緒。

多執行緒

記憶體管理器被多個執行緒併發地使用。這種實現需要包含互斥執行的**段。無論什麼時候,只能有乙個執行緒在執行乙個**段。

C 效能的程式設計技術

一 影響 c 效能的基本原理 1.i o 的開銷是最昂貴的 2.函式呼叫的開銷是乙個因素,因此我們應該內聯短小,頻繁呼叫的函式 3.複製物件的開銷是昂貴的。最好選擇按引用傳遞,而不是值傳遞。4.最好採用棧內建立物件,而不是採用堆建立物件 一般在堆內建立物件是在棧內建立物件花費的時間是 20備左右。5...

C 模板元程式設計技術

模板元程式設計 template metaprogramming 更準確的含義應該是 編 可以程式設計序的 程式 而模板元程式 template metaprogram 則是 可以程式設計序的 程式 也就是說,我們給出 的產生規則,編譯器在編譯期解釋這些規則並生成新 來實現我們預期的功能。讓我們來看...

c 程式設計技術之 初衷

從開始接觸計算機這個行業,到現在已經接近十年了,最大的感觸就是 自己費盡心思得到的結論,由於專案進度的原因,總不能很好的總結,當再次用到的時候,發現忘個差不多了。雖然基本思想還是清楚的,但是思想到應用還是有一段距離的 在這個行業,時間就是金錢,工作其實蠻簡單的,無非就是迴圈和判斷。但前提是你要徹底理...