当前位置: 首页 > 科技观察

研究了一波RTTI,你知道吗?

时间:2023-03-18 09:53:14 科技观察

最近研究了一波RTTI,整理了一些知识点,分享到这里,下面是目录:RTTI是RunTimeTypeInformation的缩写,字面意思是运行期间的类型信息,它的主要作用是动态判断运行周期的类型。一般用在dynamic_cast和typeid中。比如父类B的指针转换子类A的指针,dynamic_cast会判断B是否是A的父类,如果不是则返回nullptr,比强制传递更安全。基于什么判断?它是RTTI。先看下面这段代码:#includeusingstd::cout;usingstd::endl;classBase{public:inta;intb;Base(){cout<func();Base*b=static_cast(d);b->func();b->basefunc();Derive*b1=dynamic_cast(b);Derive*b2=static_cast(b);b1->func();b2->func();BaseBB*b3=dynamic_cast(b);BaseBB*b4=reinterpret_cast(b);cout<(b);^test_rtti.cc:69:18:error:useofdynamic_castrequires-frttiBaseBB*b3=dynamic_cast(b);^3errorsgenerated。可以看出,使用-fno-rtti编译时,使用typeid或dynamic_cast时会报错,即使用-fno-rtti编译会禁止我们使用dynamic_cast和typeid。那么他们为什么被禁止呢?1.RTTI的空间开销非常大:每一个有vtable的类(至少有一个虚方法)都会得到RTTI信息,RTTI信息包括类名及其基类信息。此信息用于实现typeid运算符以及dynamic_cast。(可以自己写代码来验证问题的大小)2.速度慢,运行时多了一层判断,所以性能肯定更慢。Tips:我这里去掉了typeid和dynamic_cast重新编译。结果表明,加上-fno-rtti后多态仍然可以正常使用,不用担心禁用rtti会影响多态的使用。我们都知道RTTI信息存在于虚函数表中,加入-fno-rtti表示禁止RTTI。虚函数表中还会有rtti信息吗?我使用clang命令检查虚函数表:clang-Xclang-fdump-vtable-layouts-stdlib=libc++-fno-rtti-ctest_rtti.cctest_rtti.cc:51:17:warning:'override'keywordisaC++11extension[-Wc++11-extensions]voidfunc()override^OriginalmapvoidDerive::func()->voidBase::func()Vtablefor'Derive'(3entries).0|offset_to_top(0)1|DeriveRTTI--(Base,0)vtableaddress----(Derive,0)vtableaddress--2|voidDerive::func()VTableindicesfor'Derive'(1entries).0|voidDerive::func()通过结果可以看出即使-fno加上了-rtti,虚函数表里还是会有RTTI指针的,但是我看了很多文档,都说rtti会增加可执行文件的大小(毕竟-fno-rtti最大的目的就是为了减少代码和可执行文件的大小),所以我估计指针指向的块中可能没有任何信息。不,具体情况不明。