首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >放置外部虚拟表

放置外部虚拟表
EN

Stack Overflow用户
提问于 2012-08-19 06:19:32
回答 1查看 1.7K关注 0票数 5

大型C++软件设计 (Lakos),第652页:

问题是,“编译器将在哪个唯一的翻译单元中保存给定类的虚拟表定义?”CFRONT (和许多其他C++实现)使用的技巧是将外部虚拟表放置在转换单元中,该转换单元定义类中出现的第一个非内联函数(如果存在的话)。

对于最常用的编译器(GCC和VisualC++),情况仍然是这样吗?或者曾经有过?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-08-19 10:27:36

GCC恰巧将其行为记录为问题(http://gcc.gnu.org/onlinedocs/gcc/Vague-Linkage.html)中所描述的:

VTables C++虚拟函数是在大多数编译器中使用一个查找表(称为vtable )实现的。vtable包含指向类提供的虚拟函数的指针,类的每个对象都包含指向其vtable (或vtable,在某些多继承情况下)的指针。如果类声明任何非内联、非纯虚拟函数,则第一个函数被选择为该类的“key方法”,并且vtable仅在定义key方法的转换单元中发出。 注意:如果选择的key方法稍后被定义为内联,则vtable仍将在定义它的每个翻译单元中发出。确保任何内联虚拟化都在类主体中被声明为内联,即使它们没有在类体中定义。

然而,即使在跨几个对象文件中可能存在多个vtable的情况下(例如,如果“key方法”最终是内联的),编译器也会安排在可能的情况下忽略重复项,但是如果目标不支持COMDAT,重复项可能会在最终的二进制文件中使用空间:

当在ELF系统(如GNU/Linux或Solaris 2 )或Microsoft上使用GNU版本2.8或更高版本时,这些构造的重复副本将在链接时丢弃。这就是所谓的COMDAT支持。 对于不支持COMDAT但支持弱符号的目标,GCC将使用它们。这样,一个副本将覆盖所有其他副本,但未使用的副本仍将占用可执行文件中的空间。 对于不支持COMDAT或弱符号的目标,大多数具有模糊链接的实体将作为本地符号发出,以避免链接器产生重复的定义错误。然而,这不会发生在内联的局部静力学中,因为拥有多个副本几乎肯定会破坏事物。

GCC似乎使用了一个以__ZTV开头的符号作为vtable。

就MSVC而言,使用VC++10进行的一些经验测试(我认为MS没有记录行为)表明,VC似乎没有试图将vtable限制在单个对象文件上。因为Microsoft知道它可以依赖支持COMDAT部分的链接器,而且由于构造函数是唯一直接使用vtable的函数(我相信,所有其他vtable使用都是通过对象指针间接使用的),所以它看起来就像VC只在构造函数实例化的任何对象文件中放置vtable的副本。对于使用编译器生成的ctor的类,它将在构造该类型的对象的任何地方。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12024642

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档