日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

string类有可以调换方向的函数吗_深度剖析C++中的inline函数

發布時間:2023/12/2 c/c++ 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 string类有可以调换方向的函数吗_深度剖析C++中的inline函数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

點藍色字關注“CurryCoder”

微信公眾號:CurryCoder的程序人生?

怕什么真理無窮,進一寸有一寸的歡喜


1.inline函數的愛恨兩難

內聯函數比宏優點好很多,詳細原因請參見盡量以const、enum、inline替換#define?。調用內聯函數不需要承受函數調用所導致的額外內存開銷,編譯器最優化機制通常被設計用來濃縮那些“不含函數調用”的代碼,所以當一個函數為內聯函數時,或許編譯器就因此有內聯對其執行語境相關的最優化。“世界上沒有免費的午餐”,內聯函數背后的整體思想是:對一個函數的調用都以函數本體替換它,但這同時會增加你的目標碼大小。在一個內存有限的機器上,過度使用內聯函數會造成程序體積太大。即使用有虛擬內存,內聯函數造成的代碼膨脹也會導致額外的換頁行為,降低指令高速緩存器的命中率。另一方面來說,如果內聯函數的本體很小,編譯器針對函數本體所產生的碼可能比函數調用所產生的碼更小。因此,將函數設置為inline,確實導致更小的目標碼和較高的命中率。

2.inline函數卑微在線求助

inline只是對編譯器的一個申請建議,不是強制命令,編譯器可以選擇對你的建議置之不理。這項申請可以隱式聲明也可以顯式聲明,隱式聲明是將函數定義在類的內部,如下所示:class?Person{
public:
????//?...
????int?age()?const?{return?mAge;}???//?隱式的內聯函數
private:
????int?mAge;
};
顯式聲明的方法則是在函數定義式前面加上關鍵字inline,如下面函數模板:template<typename?T>
inline?const?T&?max(const?T&?a,?const?T&?b){
????return?a?}
上述顯式的聲明方法中,值得注意的一點是:inline函數和函數模板通常都被定義于頭文件中。但是,函數模板未必一定是內聯的!!!inline函數通常一定被放置在頭文件中,因為大多數構建環境在編譯過程中進行內聯動作,為了將一個函數調用替換為被調用函數的本體,編譯器必須知道那個函數是啥樣。內聯動作在大多數C++程序中是編譯期的行為。函數模板通常也被放置在頭文件中,因為它一旦被使用,編譯器為了將它具體化,需要知道它的樣子。某些構建環境中,可以在連接期執行模板具體化,只不過編譯期完成具體化的動作比較常見。3.inline函數與虛函數的愛恨糾纏

大部分編譯器拒絕將太復雜(帶有循環或遞歸、switch-case語句)的函數設置為inline,而且所有對虛函數的調用也都會使inline失效。這是因為虛函數是直到運行期才會確定調用哪個函數,而inline函數意味著執行前先把調用動作替換為被調用函數的本體,編譯器工作在編譯期。如果編譯器都不知道該調用哪個函數,你也就明白了為啥虛函數不建議設置為inline。更多詳情原因請看這里https://www.jianshu.com/p/84a8335444dd

4.糟糕的內聯選擇:構造函數與析構函數

不要被你的眼睛所欺騙,下面子類構造函數真的是空的嗎???

class?Base{
public:
????//?...
private:
????string?bm1,?bm2;
};

class?Derived:?public?Base{
public:
????Derived(){}??// Derived構造函數真的是空的嗎???
????//?...
private:
????string?dm1,?dm2,?dm3;
};
當你使用new,動態創建的對象被其構造函數自動初始化;當你使用delete,對應的析構函數會被調用。當你創建一個對象時,基類及其每個成員變量都會被自動構造;當你銷毀一個對象時,從子類開始執行析構動作。如果有個異常在對象構造期間拋出,該對象已構造好的那一部分會被自動銷毀。你的程序內一定有某些代碼讓那些事情發生,這些代碼即編譯器在編譯期間產生并安排在你代碼中的某個地方。有時候,可能就存在于你的構造函數和析構函數中。上面表面上看起來空的Derived構造函數所產生的代碼,如下所示:Derived::Derived(){
????Base::Base();
????try{
????????dm1.string();
????}
????catch(...){
????????Base::~Base();
????????throw;
????}

????try{
????????dm2.string();
????}
????catch(...){
????????dm1.string();
????????Base::~Base();
????????throw;
????}

?????try{
????????dm3.string();
????}
????catch(...){
????????dm2.string();
????????dm1.string();
????????Base::~Base();
????????throw;
????}
}
上面的代碼并不能代表編譯器真正產生的代碼,因為真正的編譯器會以更復雜的做法來處理異常。盡管如此,上面的代碼已經能反映Derived的空白構造函數必須提供的行為。不論編譯器在其內部所做的異常處理有多么復雜,Derived構造函數至少一定會陸續調用成員變量和基類兩者的構造函數,而那些調用會影響編譯器是否對此空白函數執行內聯動作。最后,程序庫的設計者必須知道:內聯函數無法隨著程序庫的升級而升級。如果fun()是程序庫中的一個內聯函數,客戶將fun()本體編進其程序中,一旦程序庫設計者決定改變fun(),所有用到函數f()的客戶端程序都必須重新編譯。如果fun()是non-inline函數,一旦它有所修改客戶端只需要重新連接即可。對程序開發而言,大部分調試器對內聯函數都束手無策,因為你無法在一個并不存在的函數內部設置斷點進行調試呢?哪些函數可以設置為inline呢?我的建議是:首先不要將任何函數聲明為inline,或者將inline實施范圍局限在那些一定可以成為inline的場合。5.總結(1) 將大多數inline行為限制在小型、被頻繁調用的函數身上。這可以使以后的調試過程和二進制升級更容易,也可以使潛在的代碼膨脹問題最小化。(2) 不要只是因為函數模板出現在頭文件中,就將它們聲明為inline。

覺得不錯,請一鍵三連吧↓

總結

以上是生活随笔為你收集整理的string类有可以调换方向的函数吗_深度剖析C++中的inline函数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。