自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

研究了一波RTTI,你會(huì)了嗎

開(kāi)發(fā) 前端
RTTI 是 Run Time Type Information 的縮寫(xiě),從字面上來(lái)理解就是運(yùn)行時(shí)期的類(lèi)型信息,它的主要作用就是動(dòng)態(tài)判斷運(yùn)行時(shí)期的類(lèi)型。

最近研究了一波RTTI,整理了一下知識(shí)點(diǎn),在這里分享一下,下面是目錄:

RTTI 是 Run Time Type Information 的縮寫(xiě),從字面上來(lái)理解就是運(yùn)行時(shí)期的類(lèi)型信息,它的主要作用就是動(dòng)態(tài)判斷運(yùn)行時(shí)期的類(lèi)型。

一般在dynamic_cast和typeid中用到,例如父類(lèi)B的指針轉(zhuǎn)換子類(lèi)A的指針,dynamic_cast會(huì)判斷B究竟是不是A的父類(lèi),如果不是,會(huì)返回nullptr,相對(duì)于強(qiáng)轉(zhuǎn)會(huì)更加安全。依據(jù)什么判斷的呢?就是RTTI。

先看下面這段代碼:

  1. #include <iostream> 
  2. using std::cout; 
  3. using std::endl; 
  4. class Base 
  5. public
  6.     int a; 
  7.     int b; 
  8.     Base() 
  9.     { 
  10.         cout << this << " Base \n"
  11.     } 
  12.     virtual void func() 
  13.         cout << this << " hello Base \n"
  14.     }; 
  15.     void basefunc() 
  16.         cout << this << " hello basefunc \n"
  17.     } 
  18. }; 
  19. class BaseBB 
  20. public
  21.     int d; 
  22.     int c; 
  23.     BaseBB() 
  24.     { 
  25.         cout << this << " BaseBB \n"
  26.     } 
  27.     virtual void func() 
  28.         cout << this << " hello BaseBB \n"
  29.     } 
  30. }; 
  31. class Derive : public Base 
  32. public
  33.     Derive() 
  34.     { 
  35.         cout << this << " Derive \n"
  36.     } 
  37.     void func() override 
  38.         cout << this << " hello Derive \n"
  39.     } 
  40. }; 
  41. int main() 
  42.     Derive *d = new Derive; 
  43.     typeid(d); 
  44.     d->func(); 
  45.     Base *b = static_cast<Base *>(d); 
  46.     b->func(); 
  47.     b->basefunc(); 
  48.     Derive *b1 = dynamic_cast<Derive *>(b); 
  49.     Derive *b2 = static_cast<Derive *>(b); 
  50.     b1->func(); 
  51.     b2->func(); 
  52.     BaseBB *b3 = dynamic_cast<BaseBB *>(b); 
  53.     BaseBB *b4 = reinterpret_cast<BaseBB *>(b); 
  54.     cout << d << " " << b << " " << b1 << " " << b2 << " " << b3 << " " << b4 << endl; 
  55.     return 0; 

結(jié)果如下:

  1. clang++ test_rtti.cc -std=c++11;./a.out 
  2.  
  3. 0x7fe80ac05920 Base  
  4. 0x7fe80ac05920 Derive  
  5. 0x7fe80ac05920 hello Derive  
  6. 0x7fe80ac05920 hello Derive  
  7. 0x7fe80ac05920 hello basefunc  
  8. 0x7fe80ac05920 hello Derive  
  9. 0x7fe80ac05920 hello Derive  
  10. 0x7fe80ac05920 0x7fe80ac05920 0x7fe80ac05920 0x7fe80ac05920 0x0 0x7fe80ac05920 

上面的代碼是正常的一段使用多態(tài)的代碼,同時(shí)也包含了子類(lèi)指針轉(zhuǎn)基類(lèi)指針,基類(lèi)指針轉(zhuǎn)子類(lèi)指針,從輸出結(jié)果中可以看到,使用dynamic_cast進(jìn)行不合理的基類(lèi)子類(lèi)指針轉(zhuǎn)換時(shí),會(huì)返回nullptr,而強(qiáng)轉(zhuǎn)則不會(huì)返回nullptr,運(yùn)行時(shí)肯定就會(huì)出現(xiàn)奇奇怪怪的錯(cuò)誤,比較難排查。

如果在編譯時(shí)加上-fno-rtti會(huì)怎么樣?結(jié)果是這樣:

  1. clang++ test_rtti.cc -std=c++11 -fno-rtti 
  2.  
  3. test_rtti.cc:60:5: error: use of typeid requires -frtti 
  4.     typeid(d); 
  5.     ^ 
  6. test_rtti.cc:65:18: error: use of dynamic_cast requires -frtti 
  7.     Derive *b1 = dynamic_cast<Derive *>(b); 
  8.                  ^ 
  9. test_rtti.cc:69:18: error: use of dynamic_cast requires -frtti 
  10.     BaseBB *b3 = dynamic_cast<BaseBB *>(b); 
  11.                  ^ 
  12. 3 errors generated. 

可以看到,加上了-fno-rtti編譯時(shí),使用typeid或dynamic_cast會(huì)報(bào)錯(cuò),即添加-fno-rtti編譯會(huì)禁止我們使用dynamic_cast和typeid。那為什么要禁止使用他們呢?

1. RTTI的空間成本非常高:每個(gè)帶有vtable(至少一個(gè)虛擬方法)的類(lèi)都將獲得RTTI信息,其中包括類(lèi)的名稱(chēng)及其基類(lèi)的信息。此信息用于實(shí)現(xiàn)typeid運(yùn)算符以及dynamic_cast。(大小問(wèn)題大家可以自己編寫(xiě)代碼驗(yàn)證一下)

2. 速度慢,運(yùn)行時(shí)多判斷了一層,性能肯定更慢一些。

tips:我這里又將typeid和dynamic_cast去掉重新編譯,結(jié)果表明添加了-fno-rtti,還是可以正常使用多態(tài),所以大家不用擔(dān)心rtti的禁用會(huì)影響多態(tài)的使用。

都知道RTTI信息是存在于虛函數(shù)表中,而添加-fno-rtti后代表禁止了RTTI,那虛函數(shù)表中還會(huì)有rtti信息嗎?

我這里使用clang的命令查看一下虛函數(shù)表:

  1. clang -Xclang -fdump-vtable-layouts -stdlib=libc++ -fno-rtti -c test_rtti.cc 
  2.  
  3. test_rtti.cc:51:17: warning: 'override' keyword is a C++11 extension [-Wc++11-extensions] 
  4.     void func() override 
  5.                 ^ 
  6. Original map 
  7.  void Derive::func() -> void Base::func() 
  8. Vtable for 'Derive' (3 entries). 
  9.    0 | offset_to_top (0) 
  10.    1 | Derive RTTI 
  11.        -- (Base, 0) vtable address -- 
  12.        -- (Derive, 0) vtable address -- 
  13.    2 | void Derive::func() 
  14.  
  15. VTable indices for 'Derive' (1 entries). 
  16.    0 | void Derive::func() 

通過(guò)結(jié)果可以看到,即使添加了-fno-rtti,虛函數(shù)表中還是會(huì)存在RTTI指針,但是我查看很多文檔都說(shuō)rtti會(huì)導(dǎo)致可執(zhí)行文件的體積增大一些(畢竟-fno-rtti最大的目的就是為了減小代碼和可執(zhí)行文件的大小),所以我估計(jì)指針指向的塊里面可能什么信息都沒(méi)有,具體就不得而知了。

 

責(zé)任編輯:武曉燕 來(lái)源: 程序喵大人
相關(guān)推薦

2022-12-07 10:17:32

WindowsANSI

2022-04-19 08:28:34

main函數(shù)

2021-11-08 12:44:48

AndroidC++內(nèi)存

2021-01-01 09:03:44

故障HAProxy服務(wù)器

2024-01-02 12:05:26

Java并發(fā)編程

2023-08-01 12:51:18

WebGPT機(jī)器學(xué)習(xí)模型

2022-04-01 08:23:17

InputstreString字符串

2023-01-10 08:43:15

定義DDD架構(gòu)

2024-02-04 00:00:00

Effect數(shù)據(jù)組件

2023-07-26 13:11:21

ChatGPT平臺(tái)工具

2024-01-19 08:25:38

死鎖Java通信

2014-07-17 09:05:29

2023-03-10 22:08:20

2020-08-06 17:16:47

抖音Tiktok美國(guó)

2021-09-01 13:46:07

GitHub Copi漏洞代碼訓(xùn)練

2024-03-01 08:13:45

Shell編程解釋器

2021-09-03 05:03:58

模塊命令項(xiàng)目

2024-09-26 09:10:08

2023-05-09 08:25:26

Gaussdb數(shù)據(jù)庫(kù)開(kāi)源數(shù)據(jù)庫(kù)

2022-06-16 07:50:35

數(shù)據(jù)結(jié)構(gòu)鏈表
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)