编译器是否为未使用的类生成虚函数表
Does compiler generate vtable for a class that is not used
你能解释一下编译器是否为一个有虚函数的类生成虚表,并且没有使用这个类(没有以任何形式创建的对象)。例如,
class A {
public:
virtual void func() { }
};
int main()
{
return 0;
}
对于上面的程序,编译器是否为类A创建虚变量表?这可能是一个重复的问题,但我想知道答案。如果它是重复的,请提供链接到来源。
我花了一些时间在gcc.godbolt.org服务上(非常感谢@RudolfsBundulis),尝试在什么情况下编译器会生成虚拟表,以满足我的好奇心。
class A {
public:
virtual void func() { }
};
class B : public A {
public:
void func() final override {};
};
int main()
{
return 0;
}
任何抽象类的声明和实现都不会让编译器创建所有的东西(即使是这些类!)但是,这也取决于编译器的优化级别:
-O1
在任何编译器生成这样的main:int main() { A *a = new B; return 0; }
-O2
允许生成vtable
和其他东西,但不适用任何编译器。我检查了最新的clang(3.6, 3.7)和gcc(4.9.2, 5.1.0),它只由gcc 4.9.2
生成。-O3
在clang (3.6, 3.7), gcc(5.1.0)上不生成任何东西。但是,它们会这样做,除非你有一个实际的调用:int main() { A *a = new B; a->func(); return 0; }
但请注意,
gcc 4.9.2
仍然生成它,即使-O3
和没有调用a->func()
!
所以,答案并没有改变@tenfour所说的-它确实依赖于编译器,取决于它的优化级别,甚至是编译器的版本。在这项研究中,真正有趣的是gcc 4.9.2
仍然编译它,而不是真正需要的,尽管这种行为在gcc 5.1.0
中被修复了。
虚值表的概念是一个实现细节,而不是c++标准的一部分。当编译器需要虚函数表时,就创建一个。
在您的示例中,该类永远不会被使用,并且编译器根本不会生成任何代码。
但是,即使您实例化类并调用具有副作用的函数,如果您从不使用需要虚参表的特性,则不需要生成虚参表。
相关文章:
- 函数是否可以访问传递给main()的参数
- 根据某个函数是否存在启用模板
- 无论如何,我可以确定构造函数是否存在吗?
- 在 nullptr 上调用无状态类的非静态成员函数是否合法?
- 如何检查函数是否在LLVM Instrumentation pass的ModulePass的系统头文件中定义?
- 如果 C 函数仍然可以间接执行(通过回调函数),那么将它声明为静态函数是否是一种不好的做法?
- 在对象构造期间,将指向尚未构造的子对象的指针传递给另一个子对象的构造函数是否危险?
- 某些 boost::asio 异步函数是否将处理程序连接到操作,以便处理程序被触发一次?
- 调用 erase() 函数是否也会在擦除元素之前更改迭代器值?
- 由并发无序映射查找线程调用的函数是否安全?
- 使用静态成员函数而不是普通函数是否有任何开销?
- 从其存储的回调中删除 std::函数是否安全
- 析构函数是否会自动调用 delete[] C++?
- 构造函数是否有一种现代C++方法来了解其'container'类?
- 循环中本地对象的析构函数是否保证在下一次迭代之前被调用?
- 移动构造函数是否C++过时?
- 在 c++ 中将对象设置为等于同一类的构造函数是否有效?
- 此函数是否会在C++中创建内存泄漏?
- 具有默认值的单个参数构造函数是否与默认构造函数相同?
- 如何检测构造函数是否与抛出的析构函数无关