【问题标题】:Will compiler create vtable irrespective of object creation in c++编译器是否会创建 vtable 而不管 C++ 中的对象创建如何
【发布时间】:2019-11-19 04:49:52
【问题描述】:
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。所以我认为不需要创建。

我说的对吗?

【问题讨论】:

  • 这完全取决于实现。如果你想要一些关于什么应该是真实的通用声明,那么你会感到失望 - 没有一般要求编译器创建或不创建给定代码的 vtables。
  • 从代码大小优化的POV问?

标签: c++ gcc virtual-functions vtable


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    试图查看编译后的 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。

    【讨论】:

    • 但是请注意,如果您启用优化,gcc 不会发出 vtable,例如-O2 在任何一种情况下,因为它实际上都不需要。
    【解决方案3】:

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

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

    链接器可能会丢弃不需要的符号。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-25
      • 2011-01-20
      • 1970-01-01
      相关资源
      最近更新 更多