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

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

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

2020-01-26 14:18:46
字體:
來源:轉載
供稿:網友

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++對象占用內存的全面分析全部內容了,希望大家多多支持武林網~

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品综合不卡av| 一本大道香蕉久在线播放29| 欧美黑人视频一区| 欧美午夜性色大片在线观看| 国产亚洲欧美另类中文| 国产69精品久久久久久| 北条麻妃一区二区三区中文字幕| 亚洲国产成人精品久久| 久久国产精品久久国产精品| 国产aⅴ夜夜欢一区二区三区| 亚洲激情在线视频| xxxx欧美18另类的高清| 国产精品极品美女粉嫩高清在线| 欧美日韩精品中文字幕| 亚洲欧美日韩第一区| 欧美片一区二区三区| 97人洗澡人人免费公开视频碰碰碰| 亚洲乱码av中文一区二区| 国产精品爽爽爽爽爽爽在线观看| 亚洲人成电影网| 九九热r在线视频精品| 国产精品一区二区久久精品| 国产精品一区二区三区久久| 在线视频欧美日韩| 亚洲福利视频在线| 茄子视频成人在线| 亚洲第一页在线| 久久高清视频免费| 日韩av黄色在线观看| 精品久久久久久久久久国产| 欧美亚洲视频一区二区| 97在线观看免费| 日韩av综合网| 国产精品日韩久久久久| 理论片在线不卡免费观看| 最近2019中文字幕mv免费看| 久久久久久久久国产| 日韩欧美在线播放| 色综合视频一区中文字幕| 成人免费看黄网站| 亚洲欧美另类国产| 中文字幕久精品免费视频| 日韩精品在线看| 国产一区二区三区视频| 久久国产精品影片| 国产欧美一区二区| 日本免费一区二区三区视频观看| 日韩视频在线免费| 欧美精品www在线观看| 亚洲毛片在线观看| 92国产精品视频| 国产精品自产拍在线观看中文| 亚洲第一男人av| 欧美一级片久久久久久久| 久久免费成人精品视频| 中文字幕av一区二区三区谷原希美| 亚洲一二在线观看| 精品magnet| 北条麻妃久久精品| 国产精品电影网站| 日韩av免费在线播放| 久久亚洲精品成人| 日韩欧美国产免费播放| 九九久久久久久久久激情| 欧美大人香蕉在线| 亚洲a∨日韩av高清在线观看| 2025国产精品视频| 91嫩草在线视频| 浅井舞香一区二区| 日韩欧美成人网| 色综合久久88| 国产不卡一区二区在线播放| 亚洲乱码av中文一区二区| 亚洲精品不卡在线| 欧美成人合集magnet| 久久免费视频观看| 亚洲欧美在线x视频| 国产成人一区二区三区| 亚洲新中文字幕| 中文字幕亚洲综合久久| 夜色77av精品影院| 国产精品欧美激情| 国产精品色悠悠| 亚洲一区二区日本| 亚洲另类图片色| 欧美在线视频播放| 国产成人啪精品视频免费网| 日韩国产精品亚洲а∨天堂免| 久久精品视频导航| 国产精品美女久久久免费| 国产精品欧美日韩一区二区| 日韩欧美在线第一页| 久久久亚洲天堂| 午夜精品久久久久久久99黑人| 日韩最新中文字幕电影免费看| 欧美自拍视频在线观看| 成人a在线观看| 国产精品丝袜久久久久久高清| 亚洲精品视频中文字幕| 亚洲一级一级97网| 国产欧美日韩免费看aⅴ视频| 欧美xxxwww| 欧美精品在线网站| 久久99视频免费| 国产亚洲一级高清| 国产精品电影久久久久电影网| 亚洲最大的免费| 2019日本中文字幕| 在线视频欧美日韩| 欧美日本高清视频| 亚洲欧美日韩直播| 8x拔播拔播x8国产精品| 久久免费观看视频| 亚洲人永久免费| 主播福利视频一区| 色在人av网站天堂精品| 久久精品电影一区二区| 国产经典一区二区| 日韩欧美a级成人黄色| 欧美成人中文字幕| 精品久久久av| 国产自产女人91一区在线观看| 亚洲区免费影片| 亚洲精品在线视频| 欧美日韩国产精品一区| 成人亚洲欧美一区二区三区| 国产成人涩涩涩视频在线观看| 成人免费淫片aa视频免费| 国产精品久久久久久久久久东京| 成人午夜高潮视频| 国产99久久精品一区二区 夜夜躁日日躁| 欧日韩在线观看| 性欧美办公室18xxxxhd| 中文字幕在线看视频国产欧美在线看完整| 91免费观看网站| 国产精品对白刺激| 成人信息集中地欧美| 亚洲国产精品成人一区二区| 久久人人爽人人爽人人片av高清| 精品亚洲va在线va天堂资源站| 国产欧美一区二区三区在线看| 人妖精品videosex性欧美| 亚洲男人天堂视频| 精品视频偷偷看在线观看| 91香蕉嫩草神马影院在线观看| 欧美激情一区二区三区高清视频| 欧美日韩亚洲一区二区三区| 久久国产精品99国产精| 欧美伊久线香蕉线新在线| 亚洲精品福利在线观看| 久久精品久久精品亚洲人| 精品久久久久久国产| 黄色一区二区在线观看| 国产精品久久久久久av下载红粉| 欧美激情一二区| 91av在线精品| 亚洲一品av免费观看| 久久亚洲精品中文字幕冲田杏梨| 久久伊人色综合| 欧美视频二区36p| 日韩在线播放视频| 日韩中文字幕国产精品| 富二代精品短视频| 97人洗澡人人免费公开视频碰碰碰|