Modern C++ - inline & 什麼是內聯函式/內嵌靜態變數

563天前 · 程式設計 · c++ · 1696次阅读

Modern C++ - inline

inline 是一個C++聲明符,直譯爲⌈在行內⌋。
顧名思義,inline 希望編譯器在函式調用的地方直接插入函式的代碼。

這就是 C++ inline (內聯/內嵌)。

內聯函式

現代C++中,通常你並不需要手動聲明 inline ,這是因爲內聯只是一個⌈建議⌋。

如果函式內聯展開,可以避免函式調用的堆棧操作等開銷。

現代編譯器非常聰明,它可以自動選擇內聯候選函式。
即便你並沒有爲函式聲明inline,也有可能被編譯器內聯。

現代C++中 inline的意義已經變更爲允許重複定義

inline如何解決重複定義?

在C++中,每個普通函式都需要一個且只能有一個函式定義
當多個翻譯單元中有同一函式的多個定義時,將會引發鏈接錯誤(link err)。 (如果在一個翻譯單元中有多個定義將引發編譯錯誤,這與編譯原理相關)

inline聲明符可以允許同一個函式在多個翻譯單元中的重複定義,而不產生鏈接錯誤。
使其能夠在多個翻譯單元中使用 only header 的方式來共享函式定義

範例代碼:

//test.hpp
void func(){} //定義函式,Error.每個include此檔案的翻譯單元中都將有一個定義。
inline void func2(){} //內聯函式,Ok。允許了在多個翻譯單元中的重複定義。
void func3(); //僅聲明,Ok。需要在任意 一個 翻譯單元中定義,通常推薦對應的翻譯單元。

//test.cpp
#include "test.hpp"

//如果沒有定義func3將引發鏈接錯誤:找不到 __void __func3(...)...的定義。
void func3(){
    func();//鏈接錯誤,重複定義 __void __func(...)...。
    func2();//Ok,允許重複定義,每個翻譯單元調用自己的函式定義。
} 

//main.cpp
#include "test.hpp"
int main(){
    func();//鏈接錯誤,重複定義 __void __func(...)...。
    func2();//Ok,允許重複定義,每個翻譯單元調用自己的函式定義。
    func3();//Ok,鏈接時在其他翻譯單元中查找函式位址調用。
}
tips: 完整定義在類內的成員函式是隱式內聯的,包括非成員 friend 函式、模板函式、模板類與constexpr函式/變數(c++17起)。
struct Test{
    (inline) void print(){} //聲明即定義,這是隱式內聯的
};
constexpr (inline) int sum(int l,int r){ //編譯期函式,是隱式內聯的
    return l+r;
}
template<typename T>
(inline) T make(){ //模板函式也是隱式內聯的
    return T();
}
//...

翻譯單元

翻譯單元是C++編譯時的單位,通常來說副檔名.cc .cpp表示這是一個翻譯單元

翻譯單元由檔案本身 (如.cpp檔) 和透過 #include指令導入的標頭檔(如.h .hpp)或任意內容組成。
標頭檔通常不會作爲單獨的翻譯單元存在,它用於在多個翻譯單元的專案中共享聲明和定義。

除此之外還涉及include的實作方式,因爲include實際上做的就是將檔案中的內容完整拷貝過來。
這就是爲什麼需要注意重複定義的問題。

要在多個翻譯單元之間共享類/函式,一般會在標頭檔聲明,在對應的一個翻譯單元中定義

內聯變數

inline聲明符也可以用於變數(c++17起),其作用與函式內聯基本相同。
也是可以在不同翻譯單元中重複聲明變數。

tips: inline static的變數或inline函式中含有static變數,也將保證全局只有同一個變數。
即使多個翻譯單元中都有定義。
// test.hpp
struct Test{
    inline static int i = 0; //所有實例與翻譯單元中都是同一個對象
}
inline int func(){
    static int i = 0; // 所有翻譯單元中都是同一個對象
    return ++i;
}

void call();

// test.cpp
#include "test.hpp"
void call(){
    Test t2;// 實例2
    ++t2.i; // 結果2
    int i = func(); // 結果2
}

// main.cpp
#include "test.hpp"
int main(){
    Test t1;// 實例1
    ++t1.i; // 結果1
    int i = func(); // 結果1
    call();
}

小結

inline聲明符允許了多個翻譯單元同時存在 同一個函式/變數的定義,是實現only header的方法。

類中定義的成員函式、模板與constexpr不需要聲明inline,因爲其是隱式內聯的。

inline的函式與變數同時有static變數存在時,不會影響靜態變數的存在,保證保持全局唯一。


參閱:

  1. https://en.cppreference.com/w/cpp/language/inline
👍 0

c++ modern c++ inline

最后修改于94天前

评论

贴吧 狗头 原神 小黄脸
收起

贴吧

  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡

狗头

  • 狗头
  • 狗头
  • 狗头
  • 狗头
  • 狗头
  • 狗头
  • 狗头
  • 狗头
  • 狗头
  • 狗头
  • 狗头
  • 狗头

原神

  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神

小黄脸

  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  1. IM 451天前

    博主使用的是什么博客系统和主题?非常适合我的审美呢!

    1. Hina 451天前

      我這裏是typecho喔~ 主題是這個:https://github.com/youranreus/G 。可能有客製化修改 不要啊 不要啊

      1. IM 450天前

        谢谢博主,我准备去尝试一下!

目录

avatar

Hina

曇花一現

20

文章

96

评论

8

分类

初见

NekoNet - 一個易用的,現代libcurl C++封裝庫

232天前

OwO

33

網站正在更新中...
站點正在更新功能與樣式,如有樣式錯誤,請嘗試刷新緩存