亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

由static_cast和dynamic_cast到C++對象占用內存的全面分析

2020-05-23 13:54:58
字體:
來源:轉載
供稿:網友

static_cast和dynamic_cast是C++的類型轉換操作符。編譯器隱式執行的任何類型轉換都可以由static_cast顯式完成,即父類和子類之間也可以利用static_cast進行轉換。而dynamic_cast只能用于類之間的轉換。那么dynamic_cast的存在還有什么意義呢?因為dynamic_cast提供了一個重要的特性:運行時類型檢查來保證轉換的安全性。

用static_cast轉換存在的危險

我們知道,一個基類指針不需要進行明確的轉換操作,就可以指向基類對象或者派生類對象。比如:

class Base{  //…};class Derived{  //…};int main{  Base *p = new Base();//OK  Base *p = new Derived();//OK}

上面的兩種定義都是正確的,那么如果想反過來,讓一個子類指針指向父類對象呢?如下代碼:

class Base{  //…};class Derived{  //…};int main{  Derived *p = new Base();//error  Derived *p = static_cast<Derived*>(new Base());//OK}

如果直接把Base類型的指針轉換為Derived類型的指針,那么編譯時會報錯。如果在轉換時加上static操作符則可以順利通過編譯。但是這種做法是十分危險的,在運行期時可能會出現一些難以預測和查找的錯誤。如下面代碼:

class Base{  public:    Base():m_b(4){};    int m_b;void m_funcB(){cout << "base" << endl;};};class Derived:public Base{  public:    Derived():m_d(3){};    int m_d;    void m_funcD(){cout << "derived" << endl;};};int main(){  Derived* p = static_cast<Derived*>(new Base());  cout << p->m_d << endl;  p->m_funcD();}


雖然p是Derived類型的指針,但是實際卻指向了Base對象,而Base對象不存在m_d這個數據成員,因此輸出的結果不可預測(在我的機子上一直輸出0)。正是這種不可預測才導致難以追蹤的錯誤,試想,如果執行這段代碼會崩潰,那么還是比較還排查的,但是現在并不一定崩潰,只是執行的結果和我們的預測不一致,可能將導致連環的邏輯錯誤,這就像給自己挖了一個坑或者定時炸彈。

但是很奇怪的一點是,執行p->m_funcD()這一句后,居然可以打印出”derived”。這是怎么回事?m_funcD明明是類Derived的函數,而且類Base里并不存在這個函數,這個我們留在后面說明。

利用dynamic_cast保證轉換的安全

原則上,我們不應該讓子類指針指向父類的對象。但是如果寫下了上面這樣的代碼,我們希望可以有一種檢查機制可以幫助我們發現這個問題,這樣就可以避免對轉換后的指針進行操作,造成不可預料的后果。

C++是支持運行期類型識別的(RTTI),這種機制除了幫助我們實現多態,還能在類型轉換時進行安全檢查?;氐缴厦娴拇a,我們稍作修改:

class Base{  public:    Base():m_b(4){};    int m_b;    virtual void m_funcB(){cout << "base" << endl;};};class Derived:public Base{  public:    Derived():m_d(3){};    int m_d;    void m_funcD(){cout << "derived" << endl;};};int main(){  Derived* p = dynamic_cast<Derived*>(new Base());  cout << p->m_d << endl;  p->m_funcD();}

運行結果會是什么?程序崩潰了。原因就是我們執行了p->m_d,而p這個時候是一個空指針。原因在于利用dynamic_cast進行類型轉換時會進行安全檢查,在這里我們將一個父類指針轉換為子類指針,這被認為是一個無效操作,因此返回NULL,因此p成了空指針。所以當我們利用dynamic_cast進行了轉換后,只要對得到的指針進行檢查,就可以知道轉換是否成功。static_cast則沒有提供這種檢查,這就是dynamic_cast比static_cast安全的原因。

現在稍微離開一下正題,如果把打印m_d這句注釋掉,執行p->m_funcD()這一句后,發現還是能夠打印出”derived”。等我們總結dynamic_cast和static_cast的區別后就對這個現象進行討論。

dynamic_cast和static_cast的區別:

dynamic_cast可以實現運行期類型安全檢查,是一種更加安全的方法,但是僅僅對多態類型有效,而且只能用于指針或者引用類型的轉換上。static_cast則可應用與任何類型,而且不需要類型實現了多態。static_cast的應用更加廣泛,但是dynamic_cast更加強大和安全。

對象占用內存分析:

下面看一下我們兩次提到的現象:為什么通過一個實際指向了基類對象的子類指針調用子類的方法,既然沒有出現錯誤并且可以順利調用?

一個類無非就是包含兩種成員:數據和方法。那么當我們實例化出一個對象的時候,這個對象包含了哪些東西,實際占用的內存大小是多少?寫一段代碼試一試:

class Base{  public:    Base():m_b(4){};    int m_b;    virtual void m_funcB(){cout << "base" << endl;};};class Derived:public Base{  public:    Derived():m_d(3){};    int m_d;    void m_funcD(){cout << "derived" << endl;};};int main(){  cout << sizeof(Base) << endl;    cout << sizeof(Derived) << endl;}

打印出的結果分別是8和12。

那么一個類或者說對象占用的內存到底怎么計算呢?以Base為例,首先成員變量m_b占用了4個字節,其次,由于m_funcB是虛函數,因此要有一張虛函數表,其實就是一個指向表的指針,無論是什么類型的指針,占用的大小總是4字節,因此base占用了8個字節的大小。而Derived除了繼承了Base的成員m_b之外,也保存了虛函數表的地址,還有自己的成員變量m_d,所以占用了12個字節。

或者有人會問:構造函數呢?還有虛函數本身不是還有函數體嗎?難道不用計算進去?確實,類的函數是不會存儲在實例化出來的對象里的,試想,對于每個對象,函數實現都是一樣的,如果每實例化一個對象就存儲一次函數體,不是毫無必要并且對內存使用而言是極大的浪費?

函數編譯出來后是作為代碼的一部分放在代碼段中的,因此只要我們定義了Derived指針,無論這個實際指針指向什么對象,由于程序“事先”已經知道了這個方法屬于哪個類,只要指針的類型正確,都可以正確找到調用函數的入口。所以即使我們的代碼這么寫,也是可以正確運行的:

void * p2 = (int*)0;Derived* p3= (Derived*)p2;cout << p3->m_funcD() << endl;

不管把什么地址賦給p2,都能正確地執行m_funcD函數。當然如果p3定義成其他類型,那么編譯就會出錯。

如果執行以下代碼:

void * p2 = (int*)0;Derived* p3= (Derived*)p2;cout << p3->m_d << endl;

那么程序就會出現錯誤了,因為和成員函數不同,成員變量是每個對象都會在內存中用實際的內存地址存儲,所以說成員函數屬于類,成員變量屬于各自的對象。

以上就是小編為大家帶來的由static_cast和dynamic_cast到C++對象占用內存的全面分析全部內容了,希望大家多多支持VEVB武林網~


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品视频大全| 欧美亚洲激情在线| 亚洲桃花岛网站| 日韩av在线不卡| 韩国日本不卡在线| 欧美高跟鞋交xxxxhd| 人人澡人人澡人人看欧美| 欧美日韩在线视频一区二区| 国产精品自拍视频| 亚洲自拍偷拍在线| 在线播放精品一区二区三区| 欧美黑人一级爽快片淫片高清| 国产91在线播放九色快色| 97国产suv精品一区二区62| 色噜噜亚洲精品中文字幕| 久久久久久久国产| 久久久久久av| 欧美午夜激情在线| 91av中文字幕| 久久久在线观看| 日韩在线一区二区三区免费视频| 一区二区三区国产视频| 欧美日韩在线视频首页| 国产精品普通话| 亚洲肉体裸体xxxx137| 日韩av影院在线观看| 亚洲免费av片| 日韩网站免费观看| 国产欧美在线看| 日韩精品在线观看一区二区| 亚洲视频精品在线| 亚洲欧美第一页| 国产精品一区二区久久| 欧美日韩一区二区免费视频| 欧美裸体视频网站| 午夜剧场成人观在线视频免费观看| 亚洲精品久久7777777| 夜夜躁日日躁狠狠久久88av| 亚洲天堂开心观看| 欧美成人精品不卡视频在线观看| 国产精品香蕉在线观看| 久久久国产影院| 一区二区三区四区视频| 亚洲欧美日韩国产中文专区| 欧美激情国产日韩精品一区18| 国产精品香蕉国产| 国产日韩在线精品av| 97久久精品视频| www欧美日韩| 国产成人精品在线观看| 亚洲视频在线观看免费| 国产亚洲免费的视频看| 国产精品狠色婷| 色偷偷综合社区| 日韩在线视频二区| 一本色道久久综合狠狠躁篇怎么玩| 国产自摸综合网| 亚洲成人1234| 久久精彩免费视频| 97在线视频精品| 日韩在线观看免费网站| 中文综合在线观看| 色噜噜亚洲精品中文字幕| 欧美日韩日本国产| 欧美电影免费观看大全| 最近中文字幕mv在线一区二区三区四区| 黑人狂躁日本妞一区二区三区| 久久久久亚洲精品国产| 欧美风情在线观看| 亚洲精品不卡在线| 美日韩精品免费视频| 国产日韩精品一区二区| 久久夜色精品亚洲噜噜国产mv| 青青青国产精品一区二区| 91精品国产99久久久久久| 久久精品亚洲精品| 亚洲欧美在线免费观看| 国产精品亚洲第一区| 国产日韩欧美中文| 神马久久桃色视频| 97久久久免费福利网址| 久久久久久久久爱| 国产日韩欧美夫妻视频在线观看| 亚洲国产成人一区| 色噜噜亚洲精品中文字幕| 欧美xxxx做受欧美| 精品成人国产在线观看男人呻吟| 亚洲免费人成在线视频观看| 高跟丝袜一区二区三区| 欧美性猛交99久久久久99按摩| 中文字幕亚洲欧美日韩高清| 亚洲性夜色噜噜噜7777| 一区二区在线视频播放| 欧美日韩人人澡狠狠躁视频| 98精品国产高清在线xxxx天堂| 久久久久国产精品免费网站| 91色琪琪电影亚洲精品久久| 久久视频国产精品免费视频在线| 最近2019年日本中文免费字幕| 国产精品海角社区在线观看| 在线观看视频99| 久久激情视频免费观看| 久久99久久99精品中文字幕| 国产97在线|亚洲| 久久中国妇女中文字幕| 欧美性感美女h网站在线观看免费| 91在线视频一区| 92福利视频午夜1000合集在线观看| 日韩欧美国产网站| 免费97视频在线精品国自产拍| 在线丨暗呦小u女国产精品| 热草久综合在线| 成人精品福利视频| 97香蕉超级碰碰久久免费的优势| 欧美成人精品xxx| 国产精品国产亚洲伊人久久| 中日韩美女免费视频网址在线观看| 久久精品久久久久电影| 久久精品视频一| 国产精品亚洲激情| 国产欧美日韩精品丝袜高跟鞋| 国产精品久久二区| 久久国产加勒比精品无码| www.欧美精品| 97色在线观看免费视频| 国产精品入口福利| 国产成人亚洲综合91精品| 国产欧美亚洲视频| 日韩人体视频一二区| 日韩av电影中文字幕| 久久久中精品2020中文| 亚洲成年人影院在线| 欧美又大粗又爽又黄大片视频| 超碰97人人做人人爱少妇| 伊人久久久久久久久久| 成人av在线网址| 亚洲成av人片在线观看香蕉| 亚洲综合国产精品| 成人看片人aa| 亚洲伊人久久综合| 国产99久久精品一区二区 夜夜躁日日躁| 久久久久中文字幕| 国产精品草莓在线免费观看| 午夜精品一区二区三区在线播放| 91在线无精精品一区二区| 97色伦亚洲国产| 亚洲网在线观看| 亚洲色图美腿丝袜| 色婷婷综合久久久久| 91视频免费在线| 亚洲专区国产精品| 秋霞午夜一区二区| 日韩av成人在线| 国产精品久久久久久av| 久久亚洲电影天堂| 日韩性xxxx爱| 成人黄色在线播放| 国产成人免费av电影| 国产精品美女网站| 78色国产精品| 不卡毛片在线看| 欧美性黄网官网| 午夜精品视频网站| 成人免费自拍视频|