【C/C++】深度探索c++對象模型_筆記

1. 對象內存布局

(1) 普通類(無虛函數)
  • 成員變量排列:按聲明順序存儲,但編譯器會根據內存對齊規則插入填充字節(padding)。
    class Simple {char a;      // 1字節(偏移0)int b;       // 4字節(偏移4,因對齊跳過1-3字節)double c;    // 8字節(偏移8)
    };
    // 總大小:1 + 3(padding) +4 +8 = 16字節(64位系統)
    
  • 成員函數:獨立于對象存儲,編譯時轉換為普通函數,隱式添加 this 指針參數。
(2) 含虛函數的類
  • 虛表指針(vptr):對象頭部插入一個指針,指向類的虛函數表(vtable)
  • 虛函數表(vtable):一個函數指針數組,按虛函數聲明順序存儲地址。
    class Base {
    public:virtual void func1() {}    // vtable[0]virtual void func2() {}    // vtable[1]int data;                  // 偏移8(假設vptr占8字節)
    };
    
    內存布局[vptr][data]
    vtable內容[&Base::func1, &Base::func2]

2. 虛函數與動態綁定

(1) 多態實現流程
  • 對象構造時:編譯器在構造函數中插入代碼,將 vptr 指向當前類的虛表。
  • 函數調用時:通過 vptr 找到虛表,再根據函數聲明順序索引到具體函數地址。
    Base* obj = new Derived();
    obj->func1();  // 實際調用 Derived::func1()
    
    底層偽代碼
    mov rax, [obj]        ; 獲取vptr
    call [rax + 0]        ; 調用vtable[0]處的函數
    
(2) 覆蓋與擴展
  • 派生類覆蓋虛函數:替換基類虛表中對應的函數指針。
  • 派生類新增虛函數:在虛表末尾追加新條目。
    class Derived : public Base {
    public:void func1() override {}  // 替換Base的vtable[0]virtual void func3() {}   // 追加到vtable[2]
    };
    

3. 繼承機制

(1) 單繼承
  • 內存布局:基類成員在前,派生類成員在后。
    class Base { int a; };
    class Derived : public Base { int b; };
    // 布局:[Base::a][Derived::b]
    
  • 虛函數表:派生類虛表繼承基類虛表條目并覆蓋或擴展。
(2) 多重繼承
  • 內存布局:按繼承順序排列各基類子對象,每個多態基類有自己的 vptr

    class Base1 { virtual void f1() {} };
    class Base2 { virtual void f2() {} };
    class Derived : public Base1, public Base2 {};
    

    布局[Base1 vptr][Base1 data][Base2 vptr][Base2 data][Derived data]

  • 指針調整:當將 Derived* 轉換為 Base2* 時,編譯器自動調整指針偏移。

    Derived d;
    Base2* pb2 = &d;  // 指針實際指向 Base2 子對象起始地址
    
(3) 虛繼承(解決菱形繼承)
  • 虛基類子對象共享:所有虛繼承路徑共享同一個基類實例。

    class A { int a; };
    class B : virtual public A { int b; };
    class C : virtual public A { int c; };
    class D : public B, public C { int d; };
    

    布局

    • B 部分:[B vptr][B::b][虛基類A的偏移信息]
    • C 部分:[C vptr][C::c][虛基類A的偏移信息]
    • D::d
    • 共享的 A::a(位于對象尾部)
  • 虛基類表(vbtl):存儲虛基類子對象的偏移量,供構造函數初始化時使用。


4. 構造函數與析構函數

(1) 構造過程
  • 隱式操作:編譯器在構造函數中自動插入以下代碼:
    1. 調用基類構造函數。
    2. 初始化 vptr(確保多態正確)。
    3. 初始化虛基類(若存在)。
    4. 執行成員變量的初始化列表。
    5. 執行用戶編寫的構造函數體。
(2) 虛析構函數
  • 必要性:若基類析構函數非虛,通過基類指針刪除派生類對象會導致資源泄漏(派生類析構函數不被調用)。
  • 實現:虛析構函數在虛表中占用一個條目,確保動態綁定到實際對象的析構函數。

5. 函數調用與 this 指針

(1) 成員函數調用
  • 成員函數被編譯為普通函數,首個參數為隱式 this 指針。
    // 源代碼
    void MyClass::func(int x) { ... }// 編譯后偽代碼
    void MyClass_func(MyClass* this, int x) { ... }
    
(2) 虛函數調用
  • 通過 vptrvtable 動態解析函數地址,等價于:
    // obj->virtual_func() 的底層行為
    (*(obj->vptr[n]))(obj);  // n為虛函數在表中的索引
    

6. 內存對齊與優化

  • 對齊規則:變量地址通常是其類型大小(sizeof)的整數倍。例如:
    • int(4字節)的地址需是4的倍數。
    • double(8字節)的地址需是8的倍數。
  • 手動調整對齊
    #pragma pack(1)       // 設置1字節對齊(禁用填充)
    struct Unaligned {char a;           // 偏移0int b;            // 偏移1(正常情況下會填充到偏移4)
    };
    #pragma pack()        // 恢復默認對齊
    

7. 模板與異常處理的影響

(1) 模板實例化
  • 每個模板實例化會生成獨立的代碼,可能導致代碼膨脹。例如:
    template<typename T>
    class Box { T data; }; Box<int> a;   // 生成 Box<int> 的代碼
    Box<double> b;// 生成 Box<double> 的代碼
    
(2) 異常處理
  • 棧展開(Stack Unwinding):拋出異常時,析構局部對象需要依賴虛函數表信息(若涉及多態)。

總結

《深度探索C++對象模型》揭示了C++語法背后的底層實現邏輯,理解這些機制可幫助開發者:

  1. 優化性能:通過內存布局調整減少緩存未命中(Cache Miss)。
  2. 調試復雜問題:如多態失效、內存對齊錯誤、菱形繼承問題。
  3. 避免未定義行為:如錯誤轉換指針導致的內存訪問錯誤。
  4. 設計高效類:權衡虛函數開銷與靈活性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/905979.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/905979.shtml
英文地址,請注明出處:http://en.pswp.cn/news/905979.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

湖北理元理律師事務所:債務優化中的雙維支持實踐解析

在債務壓力與生活質量失衡的社會議題下&#xff0c;法律服務機構的功能邊界正在從單一的法律咨詢向復合型支持延伸。湖北理元理律師事務所通過“法律心理”雙維服務模式&#xff0c;探索債務優化與生活保障的平衡路徑&#xff0c;其方法論或為行業提供實踐參考。 法律框架&…

Python uv包管理器使用指南:從入門到精通

Python uv包管理器使用指南&#xff1a;從入門到精通 作為一名Python開發者&#xff0c;你是否曾經為虛擬環境管理和依賴包安裝而頭疼&#xff1f;今天我要向大家介紹一個強大的工具——uv包管理器&#xff0c;它將徹底改變你的Python開發體驗。 什么是uv包管理器&#xff1f…

Windows系統安全加固

掌握的加固點&#xff1a; 用戶系統檢查 口令策略檢查 日志審計檢查 安全選項檢查 信息保護檢查 2.2.1 用戶系統檢查 #檢查系統版本內核 判斷依據&#xff1a;無 檢查方式&#xff1a;命令 msinfo32 dxdiag查看 #檢查Administrator賬號是否停用 判斷依據&#xff1a;禁…

小蝸牛撥號助手用戶使用手冊

一、軟件簡介 小蝸牛撥號助手是一款便捷實用的撥號輔助工具&#xff0c;能自動識別剪貼板中的電話號碼&#xff0c;支持快速撥號操作。最小化或關閉窗口后&#xff0c;程序將在系統后臺運行&#xff0c;還可設置開機自啟&#xff0c;方便隨時使用&#xff0c;提升撥號效率。 …

c/c++消息隊列庫RabbitMQ的使用

RabbitMQ C 消息隊列組件設計與實現文檔 1. 引言 1.1. RabbitMQ 簡介 RabbitMQ 是一個開源的消息代理軟件&#xff08;也稱為面向消息的中間件&#xff09;&#xff0c;它實現了高級消息隊列協議&#xff08;AMQP&#xff09;。RabbitMQ 服務器是用 Erlang 語言編寫的&#…

線程(二)OpenJDK 17 中線程啟動的完整流程用C++ 源碼詳解之主-子線程通信機制

深入解析OpenJDK 17中Java線程的創建與主-子線程通信機制 引言 在Java中&#xff0c;線程的創建與啟動通過Thread.start()實現&#xff0c;但底層是JVM與操作系統協作完成的復雜過程。本文基于OpenJDK 17的C源碼&#xff0c;揭秘Java線程創建時主線程與子線程的通信機制&…

多線程爬蟲語言選擇與實現

之前文中有人提到&#xff1a;想要一個簡單易用、能快速實現多線程爬蟲的方案&#xff0c;而且目標是小網站&#xff0c;基本可以確定對反爬蟲措施要求不高&#xff0c;這些就比較簡單了。 以往我肯定要考慮常見的編程語言中哪些適合爬蟲。Python、JavaScript&#xff08;Node…

AMD Vivado? 設計套件生成加密比特流和加密密鑰

概括 重要提示&#xff1a;有關使用AMD Vivado? Design Suite 2016.4 及更早版本進行 eFUSE 編程的重要更新&#xff0c;請參閱AMD設計咨詢 68832 。 本應用說明介紹了使用AMD Vivado? 設計套件生成加密比特流和加密密鑰&#xff08;高級加密標準伽羅瓦/計數器模式 (AES-GCM)…

Unity3D仿星露谷物語開發44之收集農作物

1、目標 在土地中挖掘后&#xff0c;灑下種子后逐漸成長&#xff0c;然后使用籃子收集成熟后的農作物&#xff0c;工具欄中也會相應地增加該農作物。 2、修改CropStandard的參數 Assets -> Prefabs -> Crop下的CropStandard&#xff0c;修改其Box Collider 2D的Size(Y…

list重點接口及模擬實現

list功能介紹 c中list是使用雙向鏈表實現的一個容器&#xff0c;這個容器可以實現。插入&#xff0c;刪除等的操作。與vector相比&#xff0c;vector適合尾插和尾刪&#xff08;vector的實現是使用了動態數組的方式。在進行頭刪和頭插的時候后面的數據會進行挪動&#xff0c;時…

CE17.【C++ Cont】練習題組17(堆專題)

目錄 1.P2085 最小函數值 題目 分析 方法1:暴力求解 方法2:二次函數的性質(推薦!) 代碼 提交結果 2.P1631 序列合并 分析 方法1:建兩個堆 第一版代碼 提交結果 第二版代碼 提交結果 第三版代碼 提交結果 方法2:只建一個堆 代碼 提交結果 1.P2085 最小函數值…

題單:表達式求值1

題目描述 給定一個只包含 “加法” 和 “乘法” 的算術表達式&#xff0c;請你編程計算表達式的值。 輸入格式 輸入僅有一行&#xff0c;為需要計算的表達式&#xff0c;表達式中只包含數字、加法運算符 和乘法運算符 *&#xff0c;且沒有括號。 所有參與運算的數字不超過…

DeepSeek超大模型的高效訓練策略

算力挑戰 訓練DeepSeek此類千億乃至萬億級別參數模型,對算力資源提出了極高要求。以DeepSeek-V3為例,其基礎模型參數量為67億,采用專家混合(MoE)架構后實際激活參數可達幾百億。如此規模的模型遠超單張GPU顯存容量極限,必須借助分布式并行才能加載和訓練。具體挑戰主要包…

MFC中DoDataExchange的簡明指南

基本概念 DoDataExchange 是 MFC 框架中實現數據自動同步的核心函數&#xff0c;主要用于對話框中控件與成員變量的雙向綁定。它能讓控件中的數據和成員變量自動保持一致&#xff0c;無需手動讀寫控件數據。 使用示例 1&#xff09;變量聲明 在對話框頭文件中聲明與控件對應…

FreeCAD源碼分析: Transaction實現原理

本文闡述FreeCAD中Transaction的實現原理。 注1&#xff1a;限于研究水平&#xff0c;分析難免不當&#xff0c;歡迎批評指正。 注2&#xff1a;文章內容會不定期更新。 一、概念 Ref. from What is a Transaction? A transaction is a group of operations that have the f…

C++類與對象--1 特性一:封裝

C面向對象三大特性&#xff1a; &#xff08;1&#xff09;封裝&#xff1b;&#xff08;2&#xff09;繼承&#xff1b;&#xff08;3&#xff09;多態&#xff1b; C認為萬物皆是對象&#xff0c;對象上有對應的屬性&#xff08;數據&#xff09;和行為&#xff08;方法&…

初探Reforcement Learning強化學習【QLearning/Sarsa/DQN】

文章目錄 一、Q-learning現實理解&#xff1a;舉例&#xff1a;回顧&#xff1a; 二、Sarsa和Q-learning的區別 三、Deep Q-NetworkDeep Q-Network是如何工作的&#xff1f;前處理&#xff1a;Convolution NetworksExperience Replay 一、Q-learning 是RL中model-free、value-…

WebRTC技術EasyRTC嵌入式音視頻通信SDK打造遠程實時視頻通話監控巡檢解決方案

一、方案概述? 在現代工業生產、基礎設施維護等領域&#xff0c;遠程監控與巡檢工作至關重要。傳統的監控與巡檢方式存在效率低、成本高、實時性差等問題。EasyRTC作為一種先進的實時音視頻通信技術&#xff0c;具備低延遲、高穩定性、跨平臺等特性&#xff0c;能夠有效解決這…

專題四:綜合練習(括號組合算法深度解析)

以leetcode22題為例 題目分析&#xff1a; 給一個數字n&#xff0c;返回合法的所有的括號組合 算法原理分析&#xff1a; 你可以先考慮如何不重不漏的羅列所有的括號組合 清楚什么是有效的括號組合&#xff1f;&#xff1f;&#xff1f; 1.所有的左括號的數量等于右括號的…

星云智控自定義物聯網實時監控模板-為何成為痛點?物聯網設備的多樣化-優雅草卓伊凡

星云智控自定義物聯網實時監控模板-為何成為痛點&#xff1f;物聯網設備的多樣化-優雅草卓伊凡 引言&#xff1a;物聯網監控的模板革命 在萬物互聯的時代&#xff0c;設備監控已成為保障物聯網系統穩定運行的核心環節。傳統的標準化監控方案正面臨著設備類型爆炸式增長帶來的…