typeid如何得出变量的类型?

比如一个int i=1;的代码,使用typeid(i).name()就可以知道i是什么类型,感觉好神奇,因为我的理解是程序只是给typeid传递了那个i变量的地址而已,但最后程序是如何通过这个地址求出i的类型呢?原理是什么…
关注者
106
被浏览
2869
题主先好好理解一下C++的typeid运算符到底是什么意思,再问“原理是什么”会比较好。

先看这里学习typeid是什么意思:typeid operator

针对题主给的例子:
int i = 1;
const char* name = typeid(i).name();
这里的typeid(i)根本不需要做任何运行时动作,而是纯编译时行为——它使用变量i的静态类型直接就知道这是对int类型做typeid运算,于是可以直接找出int对应的std::type_info对象返回出来。

If expression is not a glvalue expression of polymorphic type, typeid does not evaluate the expression, and the std::type_info object it identifies represents the static type of the expression. Lvalue-to-rvalue, array-to-pointer, or function-to-pointer conversions are not performed.

此时的typeid运算符就跟sizeof运算符的大部分情况一样,只需要编译器算出表达式的静态类型就足够了。
算出表达式的静态类型是C++编译器的基本功能了,类型检查、类型推导等许多功能都依赖它。


而当typeid运算符应用在一个指向多态类型对象的指针上的时候,typeid的实现才需要有运行时行为。
If expression is a glvalue expression that identifies an object of a polymorphic type (that is, a class that declares or inherits at least one virtual function), the typeid expression evaluates the expression and then refers to the std::type_info object that represents the dynamic type of the expression. If the glvalue expression is obtained by applying the unary * operator to a pointer and the pointer is a null pointer value, an exception of type std::bad_typeid or a type derived from std::bad_typeid is thrown.
实际实现的时候,通常是在类的vtable里会有个slot保存着指向该类对应的std::type_info对象的指针。

要形象的理解的话,请参考我在另一个回答里画的图:为什么bs虚函数表的地址(int*)(&bs)与虚函数地址(int*)*(int*)(&bs) 不是同一个? - RednaxelaFX 的回答
可以看到Clang++在LP64上用的vtable布局,不禁用RTTI时,在-8偏移量上的slot就是存typeinfo指针的。