Visual C++:在明显的情况下没有去虚拟化?
Visual C++ : No devirtualization in obvious cases?
看visual c++(VS2017 RC)生成的代码看到简单情况下的动态分支(虚拟调用)时,我很惊讶
所以我用编译器资源管理器尝试了以下代码:
struct Base
{
virtual void foo() = 0;
};
struct Impl : Base
{
void foo() override;
};
Impl g_impl;
void globalCall()
{
g_impl.foo();
}
void localCall()
{
Impl i;
i.foo();
}
void tempCall()
{
Impl().foo(); // dynamic branching generated!
}
struct Class
{
void memberCall();
Impl impl;
};
void Class::memberCall()
{
impl.foo(); // dynamic branching generated!
}
编译器浏览器link:
https://godbolt.org/g/RmUku2
对于临时和成员情况,看起来没有发生去虚拟化。那么这是编译器的实现质量问题,还是有这样的结果的技术正当理由?
只是错过了去虚拟化的案例。从第一个支持去虚拟化的版本VS 2013开始就是这样,其他编译器gcc、icc、clang都是去虚拟化。通常,最好明确指定 final
而不是依赖编译器迂腐地执行去虚拟化。将 Impl.foo
标记为 final
可在所有情况下启用优化。
看visual c++(VS2017 RC)生成的代码看到简单情况下的动态分支(虚拟调用)时,我很惊讶
所以我用编译器资源管理器尝试了以下代码:
struct Base
{
virtual void foo() = 0;
};
struct Impl : Base
{
void foo() override;
};
Impl g_impl;
void globalCall()
{
g_impl.foo();
}
void localCall()
{
Impl i;
i.foo();
}
void tempCall()
{
Impl().foo(); // dynamic branching generated!
}
struct Class
{
void memberCall();
Impl impl;
};
void Class::memberCall()
{
impl.foo(); // dynamic branching generated!
}
编译器浏览器link: https://godbolt.org/g/RmUku2
对于临时和成员情况,看起来没有发生去虚拟化。那么这是编译器的实现质量问题,还是有这样的结果的技术正当理由?
只是错过了去虚拟化的案例。从第一个支持去虚拟化的版本VS 2013开始就是这样,其他编译器gcc、icc、clang都是去虚拟化。通常,最好明确指定 final
而不是依赖编译器迂腐地执行去虚拟化。将 Impl.foo
标记为 final
可在所有情况下启用优化。