den*_*ced 4 c++ gcc compilation vtable visual-c++
从大型C++软件设计(Lakos),第652页:
问题是,"编译器在哪个唯一的翻译单元中存放给定类的虚拟表定义?".CFRONT(以及许多其他C++实现)采用的技巧是将外部虚拟表放置在翻译单元中,该单元定义类中出现的词法上第一个非内联函数(如果存在).
最常用的编译器(GCC和Visual C++)仍然是这种情况吗?还是曾经?
GCC碰巧记录它的行为与问题(http://gcc.gnu.org/onlinedocs/gcc/Vague-Linkage.html)中描述的一样:
的VTable
使用查找表(称为vtable)在大多数编译器中实现C++虚函数.vtable包含指向由类提供的虚函数的指针,并且该类的每个对象都包含指向其vtable(或vtable,在某些多继承情况下)的指针.如果类声明任何非内联非纯虚函数,则选择第一个作为类的"键方法",并且仅在定义键方法的转换单元中发出vtable.
注意:如果稍后将所选键方法定义为内联,则仍会在定义它的每个转换单元中发出vtable.确保在类体中内联声明任何内联虚拟内容,即使它们未在那里定义.
但是,即使在几个目标文件中可能存在多个vtable的情况下(如果'key method'变成内联的话也会发生这种情况),编译器会尽可能地忽略重复项,但重复项可能会结束.如果目标不支持COMDAT,则在最终二进制文件中使用空格:
当在GNU/Linux或Solaris 2等ELF系统上使用GNU ld 2.8或更高版本时,或者在Microsoft Windows上使用时,这些构造的副本将在链接时被丢弃.这称为COMDAT支持.
对于不支持COMDAT但支持弱符号的目标,GCC将使用它们.这样一个副本将覆盖所有其他副本,但未使用的副本仍将占用可执行文件中的空间.
对于不支持COMDAT或弱符号的目标,大多数具有模糊链接的实体将作为本地符号发出,以避免链接器出现重复的定义错误.然而,对于内联中的局部静态不会发生这种情况,因为拥有多个副本几乎肯定会破坏事物.
FWIW,GCC似乎使用了一个__ZTV以vtable 开头的符号.
就MSVC而言,VC++ 10的一些实证测试(我不认为MS记录了这种行为)表明VC似乎并没有试图将vtable限制为单个目标文件.由于Microsoft知道它可以依赖于支持COMDAT部分的链接器,并且因为构造函数是唯一直接使用vtable的函数(所有其他vtable使用是通过对象指针间接的,我相信),看起来VC只是放置了副本实例化构造函数的任何目标文件中的vtable.对于使用编译器生成的ctor的类,可以构造该类型的对象.
| 归档时间: |
|
| 查看次数: |
1400 次 |
| 最近记录: |