gpt4 book ai didi

c++ - C++ 链接器对于仅从程序中的一个类使用的虚拟方法是否聪明?

转载 作者:行者123 更新时间:2023-11-30 05:34:48 24 4
gpt4 key购买 nike

我从事一个单元测试文化极低的项目。我们的单元测试几乎为零,每个 API 都是静态的。

为了能够对我的一些代码进行单元测试,我创建了类似这样的包装器

class ApiWrapper {

virtual int Call(foo, bar) {
return ApiCall(foo, bar);
}
};

现在在我的函数中:

int myfunc() {
APiCall(foo, bar);
}

我愿意:

int myfunc(ApiWrapper* wrapper) {
wrapper->Call(foo, bar);
}

这样我就可以模拟这样的功能。问题是一些同事提示生产代码不应该受到可测试性需求的影响——我知道这是胡说八道,但事实就是如此。

无论如何,我相信我在某个地方读到过,编译器实际上很聪明,可以用直接调用替换未使用的多态行为......或者如果没有覆盖虚拟方法的类,它就会变得“正常”。

我试验过,在gcc 4.8上它没有内联或直接调用虚方法,而是创建了vt。

我尝试用谷歌搜索,但没有找到任何相关信息。这是一件事还是我记错了……或者我必须做些什么来向链接器、优化标志或其他东西解释这一点?

请注意,虽然在生产环境中这个类是最终的,但在测试环境中它不是。这正是链接器必须聪明并检测它的地方。

最佳答案

C++ 编译器只有在确定实际类型是什么的情况下,才会将多态调用替换为直接调用。

所以在下面的代码片段中,它会被优化:

void f() {
ApiWrapper x;
x.Call(); // Can be replaced
}

但在一般情况下,它不能:

void f(ApiWrapper* wrapper) {
wrapper->Call(); // Cannot be replaced
}

您还为您的问题添加了两个条件:

if there is no class that overrides a virtual method it becomes "normal".

这无济于事。 C++ 编译器和链接器都不会查看类的总数来搜索是否存在任何继承者。无论如何这是徒劳的,因为您总是可以动态加载新类的实例。

顺便说一句,这种优化确实是由一些 JVM 执行的(称为去虚拟化)——因为在 Java 领域有一个类加载器,它知道当前加载了哪些类。

in production this class is final

这会有帮助!例如,如果方法/方法的类被标记为 final,Clang 会将虚拟调用转换为非虚拟调用。

关于c++ - C++ 链接器对于仅从程序中的一个类使用的虚拟方法是否聪明?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34095732/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com