如何在不查看编译代码的情况下检查代码块是否已优化?
例如:
void Func(const int val) {
const int minVal = 100;
if(val > minVal) {
// Complex code block
}
}
...
Func(200);
for(int i = 0; i < 1000; ++i)
Func(50);
如何检查
Func(50)
以及整个 for
循环是否已优化?这个问题不能一概而论地回答。这将取决于多种因素。不同编译器的结果有所不同,代码是否会被优化将取决于优化级别。
未优化的构建(即 O0)很可能会保留检查,因为它们通常甚至不会内联任何内容以使调试更容易(因此,它永远不知道“val”有什么值。
优化的构建可以优化这种情况,但有一个问题:编译器实际上需要能够看到翻译单元中的函数定义(而不是声明)。如果您在标头中声明“func”,在 cpp 文件中定义其实现,并在另一个 cpp 文件中使用“func”,则它将无法对其进行优化,除非某种链接时代码生成是用过的。 此外,编译器评估必须确定“func”实际上是值得内联的东西。这对于小函数来说是可能的,但对于较大的函数来说,这种可能性就较小。有编译器内联某些函数的提示和说明,但这些几乎不应该使用。
但是由于我们使用的是 C++,所以让我们再回答一个问题:如果您实际上需要确保该块被优化掉,甚至在调试构建中,该怎么办?好吧,我们可以做到这一点,尽管它有缺点:
template<int Val>
void Func() {
static constexpr int minVal = 100;
if constexpr(Val > minVal) {
// Complex code block
}
}
func<200>();
使用非类型模板参数,您实际上可以为函数指定一个编译时常量参数。将“minVal”更改为实际的 constexpr 常量,我们可以使用“if constexpr”强制编译器在编译时执行此检查(至少如果您可以访问 c++17)。 现在我并不是说你应该这样做——它有明显的缺点。现在“Val”实际上必须是一个常量参数,这一次。此外,对于每个编译单元中传入的每个“Val”,它将强制同一函数的多个实例化。它会对编译时间产生负面影响。但如果您的用例出于某种原因需要它,那么它是一个选项。尽管在实践中,如果 constexpr 是您主要在元编程上下文中使用的东西,而您已经在模板函数中。