编译器将创建vtable而不考虑C ++中的对象创建

时间:2019-11-19 04:49:52

标签: c++ gcc virtual-functions vtable

class B 
{ 

public: virtual void fun1() {} 

};

class D: public B 
{ 

public: virtual void fun1() {} 

};

int main() 
{ 

//Empty Main. 

//Not creating any object of B or D. 

return 0; 

}

在GCC或Visual Studio中,编译器会在此处创建任何vTable吗?

据我所知,它不应创建任何vTable,因为我们没有创建任何B或C obj。因此,我认为无需创建。

我正确吗?

3 个答案:

答案 0 :(得分:1)

使用gcc时,会在the translation unit that defines the first non-inline virtual, but not pure virtual, method of the class中发射(创建)一个vtable。这不取决于是否创建了该类的任何对象。 (在您的示例中,没有这样的功能。但是,这似乎并不是您要问的重点,所以我将忽略它。)

不过,链接器可以随意丢弃任何可以证明未使用的东西。因此,即使编译器创建了该vtable,它也可能不会出现在最终可执行文件中。

答案 1 :(得分:1)

试图查看已编译的C ++的程序集输出 在https://godbolt.org/上,编译器为x86-64 gcc9.2

情况1: 链接:https://godbolt.org/z/jFkC4Q

class B 
{ 

public: virtual void fun1() {} 

};

class D: public B 
{ 

public: virtual void fun1() {} 

};

int main() 
{ 

//Empty Main. 

//Not creating any object of B or D. 

return 0; 

}

以上代码的结果为:

main:
  push rbp
  mov rbp, rsp
  mov eax, 0
  pop rbp
  ret

情况2: 链接:https://godbolt.org/z/WyNY9j

class B 
{ 

public: virtual void fun1() {} 

};

class D: public B 
{ 

public: virtual void fun1() {} 

};

int main() 
{ 

//Non Empty Main. 

D d; // creating object of D

return 0; 

}

以上代码的结果为:

D::fun1():
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-8], rdi
        nop
        pop     rbp
        ret
main:
        push    rbp
        mov     rbp, rsp
        mov     eax, OFFSET FLAT:vtable for D+16
        mov     QWORD PTR [rbp-8], rax
        mov     eax, 0
        pop     rbp
        ret
vtable for D:
        .quad   0
        .quad   typeinfo for D
        .quad   D::fun1()
typeinfo for D:
        .quad   vtable for __cxxabiv1::__si_class_type_info+16
        .quad   typeinfo name for D
        .quad   typeinfo for B
typeinfo name for D:
        .string "1D"
typeinfo for B:
        .quad   vtable for __cxxabiv1::__class_type_info+16
        .quad   typeinfo name for B
typeinfo name for B:
        .string "1B"

在第二种情况下,我们可以看到该vtable已创建。

答案 2 :(得分:0)

Vtables是静态数据,非常类似于常量数组。每个(简单)多态类只有一个。 (复杂的类可以有很多vtable,但这是一个细节。)

与其他任何符号一样,它可以由代码引用。如果您不创建类的实例,则不需要它,但是它将由您的类的构造函数引用(但是这些构造函数将是未引用的符号)。

链接器可能会删除不需要的符号。

相关问题