为什么 vptr 作为具有虚函数的类的内存中的第一个条目存储?

Lix*_*ixu 7 c++ compiler-construction performance memory-layout vptr

对于某些编译器,如果一个类具有虚函数,则可以使用其对象的第一个字节的地址来访问其 vptr。例如,

\n\n
class Base{\npublic:\n    virtual void f(){cout<<"f()"<<endl;};\n    virtual void g(){cout<<"g()"<<endl;};\n    virtual void h(){cout<<"h()"<<endl;};\n};\n\nint main()\n{   \n   Base b;\n\n   cout<<"Address of vtbl\xef\xbc\x9a"<<(int *)(&b)<<endl;\n\n   return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我知道它取决于不同的编译器行为。既然存在 vptr 被存储为第一个条目的情况,那么这样做有什么好处呢?这是否有助于提高性能,或者仅仅是因为使用 &b 更容易访问 vbtl?

\n

sha*_*oth 6

这是一个实现细节,但实际上许多实现都是这样做的。

是比较高效、方便的。假设您需要为给定对象调用虚拟函数。您有一个指向该对象的指针和虚函数索引。您需要以某种方式找到应该使用该索引并针对该对象调用哪个函数。sizeof(void*)好的,您只需访问指针后面的第一个字节并找到 vtable 所在的位置,然后访问 vtable 的必要元素即可获取函数地址。

您可以存储“每个对象的 vtable”或其他内容的单独映射,但如果您决定要将 vptr 存储在对象内,那么使用第一个字节而不是最后一个字节或任何其他位置才是合乎逻辑的,因为有了这个一旦你有了指向对象的指针,你就知道在哪里可以找到vptr,不需要额外的数据。