C/C++編程筆記:inline函數的總結!C/C++新手值得收藏!

来源:https://www.cnblogs.com/yxy6/archive/2020/06/02/13034663.html
-Advertisement-
Play Games

在c/c++中,為瞭解決一些頻繁調用的小函數大量消耗棧空間(棧記憶體)的問題,特別的引入了inline修飾符,表示為內聯函數。 棧空間就是指放置程式的局部數據(也就是函數內數據)的記憶體空間。 在系統下,棧空間是有限的,假如頻繁大量的使用就會造成因棧空間不足而導致程式出錯的問題,如,函數的死迴圈遞歸調用 ...


在c/c++中,為瞭解決一些頻繁調用的小函數大量消耗棧空間(棧記憶體)的問題,特別的引入了inline修飾符,表示為內聯函數。

棧空間就是指放置程式的局部數據(也就是函數內數據)的記憶體空間。

在系統下,棧空間是有限的,假如頻繁大量的使用就會造成因棧空間不足而導致程式出錯的問題,如,函數的死迴圈遞歸調用的最終結果就是導致棧記憶體空間枯竭。

上面的例子就是標準的內聯函數的用法,使用inline修飾帶來的好處我們錶面看不出來,其實,在內部的工作就是在每個for迴圈的內部任何調用dbtest(i)的地方都換成了(i%2>0)?”奇”:”偶”,這樣就避免了頻繁調用函數對棧記憶體重覆開闢所帶來的消耗

inline使用限制

inline的使用時有所限制的,inline只適合函數體內部代碼簡單的函數使用,不能包含複雜的結構控制語句例如while、switch,並且不能內聯函數本身不能是直接遞歸函數(即,自己內部還調用自己的函數)。

inline僅是一個對編譯器的建議

inline函數僅僅是一個對編譯器的建議,所以最後能否真正內聯,看編譯器的意思:

它如果認為函數不複雜,能在調用點展開,就會真正內聯,並不是說聲明瞭內聯就會內聯,聲明內聯只是一個建議而已。

建議:inline函數的定義放在頭文件中

因為內聯函數要在調用點展開,所以編譯器必須隨處可見內聯函數的定義,要不然就成了非內聯函數的調用了。所以,這要求:

每個調用了內聯函數的文件都出現了該內聯函數的定義。

因此,將內聯函數的定義放在頭文件里實現是合適的,省卻為每個文件實現一次的麻煩。

聲明跟定義要一致:

如果在每個文件里都實現一次該內聯函數的話,那麼,最好保證每個定義都是一樣的,否則,將會引起未定義的行為。如果不是每個文件里的定義都一樣,那麼,編譯器展開的是哪一個,那要看具體的編譯器而定。所以,最好將內聯函數定義放在頭文件中。

類中的成員函數與inline

定義在類中的成員函數預設都是內聯的

如果在類定義時就在類內給出函數定義,那當然最好。

如果在類中未給出成員函數定義,而又想內聯該函數的話,那在類外要加上inline,否則就認為不是內聯的。

將成員函數的定義體放在類聲明之中雖然能帶來書寫上的方便,但不是一種良好的編程風格,上例應該改成:

inline 是一種“用於實現的關鍵字”

關鍵字inline 必須與函數定義體放在一起才能使函數成為內聯,僅將inline 放在函數聲明前面不起任何作用。

如下風格的函數Foo不能成為內聯函數:

而如下風格的函數Foo則可以成為內聯函數:

因此,inline 是一種“用於實現的關鍵字”,而不是一種“用於聲明的關鍵字”。

一般地,用戶可以閱讀函數的聲明,但是看不到函數的定義。儘管在大多數教科書中內聯函數的聲明、定義體前面都加了inline 關鍵字,但我認為inline不應該出現在函數的聲明中。這個細節雖然不會影響函數的功能,但是體現了高質量C++/C 程式設計風格的一個基本原則:

聲明與定義不可混為一談,用戶沒有必要、也不應該知道函數是否需要內聯。

慎用inline

雖然說內聯函數可以提高執行效率,但是不可以將所有的函數都定義為內聯函數。

內聯是以代碼膨脹(複製)為代價,僅僅省去了函數調用的開銷,從而提高函數的執行效率。

如果執行函數體內代碼的時間,相比於函數調用的開銷較大,那麼效率的收穫會很少。另一方面,每一處內聯函數的調用都要複製代碼,將使程式的總代碼量增大,消耗更多的記憶體空間。

以下的情況不適合用內聯函數:

(1)如果函數體內的代碼比較長,使用內聯將導致記憶體消耗代價較高。

(2)如果函數體內出現迴圈,那麼執行函數體內代碼的時間要比函數調用的開銷大。類的構造函數和析構函數容易讓人誤解成使用內聯更有效。要當心構造函數和析構函數可能會隱藏一些行為,如“偷偷地”執行了基類或成員對象的構造函數和析構函數。所以不要隨便地將構造函數和析構函數的定義體放在類聲明中。一個好的編譯器將會根據函數的定義體,自動地取消不值得的內聯(這進一步說明瞭 inline 不應該出現在函數的聲明中)。

小結

內聯函數並不是一個增強性能的靈丹妙藥。只有當函數非常短小的時候它才能得到我們想要的效果;但是,如果函數並不是很短而且在很多地方都被調用的話,那麼將會使得可執行體的體積增大。

最令人煩惱的還是當編譯器拒絕內聯的時候。在老的實現中,結果很不盡人意,雖然在新的實現中有很大的改善,但是仍然還是不那麼完善的。一些編譯器能夠足夠的聰明來指出哪些函數可以內聯哪些不能,但是大多數編譯器就不那麼聰明瞭,因此這就需要我們的經驗來判斷。

如果內聯函數不能增強性能,就避免使用它!

其實做為一個編程學習者,有一個學習的氛圍跟一個交流圈子特別重要這裡我推薦一個C語言C++交流QQ群951726787,不管你是小白還是轉行人士歡迎入駐,大家一起交流成長。

————————————————

原文鏈接:https://blog.csdn.net/lym940928/java/article/details/88368363


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前端的前景怎麼樣,以下是我的分享: 隨著互聯網的高速發展,不知不覺中我們的生活已被互聯網從四面八方給包圍,不管是網上點餐,網上購物、網上購票,還是網上學習,這都表明瞭現在就是互聯網的天下。因此,也就越來越多的選擇互聯網行業,選擇學習前端開發,但是大家也有擔心的問題,最近幾年web前端發展趨勢良好,但 ...
  • HTTP 請求中,空格應該被編碼為什麼?今天我們走進 RFC 文檔和 W3C 文檔,瞭解一下這個「史詩級」大坑。 ...
  • 面向介面編程能非常有效地提高代碼質量,可以將介面和實現相分離,封裝不穩定的實現,暴露穩定的介面。上游系統面向介面而非實現編程,不依賴不穩定的實現細節,這樣當實現發生變化的時候,上游系統的代碼基本上不需要做改動,以此來降低耦合性,提高擴展性。 ...
  • 背景 最近瞭解到很多朋友對限流、熔斷、降級、隔離、超時重試的概念和應用場景理解的不是很到位,所以想用五篇的篇幅稍微系統的介紹一下。 本篇是第一篇,是限流做詳解,如果反饋好的話,我會繼續寫下麵四篇。不好的話就算了,算我理解不夠,再自己總結總結。 限流的概念 有朋友問我限流和熔斷有什麼區別,我的理解很簡 ...
  • 老孟導讀:歷時1年的時間,整理完成了330+組件的詳細用法,不僅包含UI組件,還包含了功能性的組件。 雖然整理了 330+的組件基本用法,但並不是讓你每一個都學習一遍,任何技術基本都是掌握 20%就可以解決 80%的問題,因此只需學會基礎組件就可以上手項目了,至於其他的控制項只需大概瀏覽一下,做項目的 ...
  • 19. 文件讀寫 19.1 文件操作 數據持久化,是將程式中的對象以數據的方式保存到磁碟上,在程式下次運行時,可以將數據從磁碟上恢復到記憶體中。數據持久化的方式有很多,而最為常見的方式是將數據以文件的形式保存。在Python中,可以通過內置函數的方法進行文件的讀、寫、刪除等操作。 19.1.1 文件的 ...
  • 18.目錄與文件 18.1 os和shutil 日常使用過程中,難免需要使用跟文件系統相關的標準庫。在使用Python文件系統中,常用的庫為os和shutil標準庫,方法如下所示: import os import shutil 18.1.1 遍歷文件夾 os.getcwd():獲取當前工作目錄,返 ...
  • 1 import tkinter 2 import subprocess 3 import os 4 import time 5 import re 6 import sys 7 from tkinter import Label, Button, StringVar 8 from tkinter. ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...