编译器是否会创建vtable,而不考虑在c++中创建对象

Will compiler create vtable irrespective of object creation in c++

本文关键字:不考虑 c++ 创建对象 是否 创建 vtable 编译器      更新时间:2023-10-16
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吗?

根据我的理解,它不应该创建任何vTables,因为我们没有创建任何B或C对象。所以我认为没有必要创建。

我说得对吗?

使用gcc时,在定义类的第一个非内联虚拟(但不是纯虚拟(方法的转换单元中发出(创建(vtable。这并不取决于是否创建了该类的任何对象。(在你的例子中,没有这样的函数。然而,这似乎不是你问题的重点,所以我将忽略它。(

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

尝试查看编译后的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已经创建。

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

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

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