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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Cpp 对象模型探索 / 多重继承下基类指针释放子类对象的原理说明(虚析构函数的作用)

發布時間:2024/10/14 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Cpp 对象模型探索 / 多重继承下基类指针释放子类对象的原理说明(虚析构函数的作用) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

源碼

#include <iostream>class Base1 { public:virtual void func_1_1(){ std::cout << "Base1::func_1_1()" << std::endl; }virtual void func_1_2(){ std::cout << "Base1::func_1_2()" << std::endl; }virtual ~Base1() {} };class Base2 { public:virtual void func_2_1(){ std::cout << "Base2::func_2_1()" << std::endl; }virtual void func_2_2(){ std::cout << "Base1::func_2_2()" << std::endl; }virtual ~Base2() {} };class Son :public Base1, public Base2 { public:virtual void func_s(){ std::cout << "Son::func_s()" << std::endl; }virtual void func_2_1(){ std::cout << "Son::func_2_1()" << std::endl; } };int main() {Base2 *pb2 = new Son();delete pb2;return 0; }

分析

Son類的內存布局如下所示:

在代碼 delete pb2; 處打下斷點,進入匯編,如下圖所示:

總結過程,如下:

delete pb2 時,根據 Base2 的虛函數表,找到 trunk 項,從而獲得了子類對象的首地址,并且調用子類對象的虛析構函數。然后先后執行了 Base2、Base1和Son類的虛構函數,最后完成?new Son 對象的釋放。

若是如下代碼:

Base1 *pb1 = new Son();delete pb1;

則 Base1 虛函數表中的 trunk 項對應的代碼中就不包含了調整 pb1 指針的位置,因為 pb1 本身就指向了 Son 類對象的首地址,所以直接調用了 Son 類對象的析構函數。

拓展:

1、虛函數表中的 trunk 項,實際上一段匯編代碼的首地址,執行的內容如下:

  • 將 pb2 偏移到子類對象的首地址。
  • 執行子類對象的虛析構函數。

2、上述釋放內存的成功實現的前提是,基類的析構函數必須是虛函數。若不是,則直接執行了 Base2 那部分的析構函數,這就導致了 Son 類對象時只釋放 Base2 對應的那部分。

對于操作系統的內存分配機制來說,相對于內存塊前面的固定位置會記錄著該內存塊的信息,包括該內存塊的字節數。由于上述操作中,釋放 Base2 對應的部分是時候,沒有辦法找到這部分的內存信息,從而導致了釋放內存失敗,程序運行崩潰。

?

(SAW:Game Over!)

總結

以上是生活随笔為你收集整理的Cpp 对象模型探索 / 多重继承下基类指针释放子类对象的原理说明(虚析构函数的作用)的全部內容,希望文章能夠幫你解決所遇到的問題。

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