C++ 编译器能否简化涉及函数的逻辑表达式?
一些计算布尔值的函数:C++ 编译器能否简化涉及函数的逻辑表达式?,c++,c,compiler-optimization,C++,C,Compiler Optimization,一些计算布尔值的函数: bool a() { return trueorfalse; } bool b() { //... } bool c() { //... } 这种情况 //somewhere else if((a()&&b()&&c()) || (a()&&b()&&!c()) ) { doSomething(); } 也可以写成 if(a()&&b()) { doSo
bool a()
{
return trueorfalse;
}
bool b()
{
//...
}
bool c()
{
//...
}
这种情况
//somewhere else
if((a()&&b()&&c()) || (a()&&b()&&!c()) )
{
doSomething();
}
也可以写成
if(a()&&b())
{
doSomething();
}
编译器通常会对此进行优化吗
那么纯布尔值呢:
if((a&&b&&c) || (a&&b&&!c))
{
doSomething();
}
不,他们不会。原因是优化对用户是可见的,因为它会改变可观察到的副作用。例如,在优化版本中,
c()
将永远不会执行,即使用户明确尝试执行。这可能并将导致错误 因为你的前提有缺陷,不,他们不会
(a()&&b()&&c())| |(a()&&b()&&&c())
绝对不能重写为(a()&&b())
C(和C++)不是函数式编程语言(如Haskell)。由于函数可能有副作用,因此无法以任何方式“优化”条件,因为所有函数都必须以定义良好的方式(有条件地)调用 如果确实需要优化,可以首先将结果分配给变量:
const bool ba = a(), bb = b(), bc = c();
if (ba && bb && bc || ba && bb && !bc) { /* ... */ } // probably optimized to "ba && bb"
C++11中引入的constexpr
函数如果产生一个常量表达式,则可能允许进行优化,但我不确定
您甚至可以将其压缩为:在以下代码中,f()
必须被调用两次:
if (f() && false || f() && true)
{
// ...
}
但问题是,一般来说,它不能以这种方式重构 如果任何函数的副作用改变了
c()
的结果,那么第二次调用可能会返回与第一次调用不同的结果
不仅如此,由于执行短路,事情可能会变得更加混乱。在C语言中,函数的返回值通常给出函数是否成功执行。例如,调用图形例程、转换文件。想想您使用指针更改函数外部内容的频率。或者调用另一个输出某些内容的函数。正如有人所说,这不是函数式编程 如果编译器能够确定foo()发生了变化,但什么也不做,那么它可能会简化它,但我不会指望它 下面是一个非常简单的例子
bool foo()
{
std::cout << "this needs to be printed each time foo() is called, even though its called in a logical expression\n";
return true;
}
int main()
{
if ((foo() && !(foo()) || foo() && !(foo())))
return 0;
return 1;
}
bool-foo()
{
std::难道只有在知道函数是的情况下才能这样写吗?我不这么认为,除非它能证明c在每次调用时都返回相同的结果,而且它可能还必须尝试内联c。bool c(){static bool r=true;r=!r;return r;}
例如,如果您使用变量而不是函数调用,那么,是的,编译器将进行优化。我认为值得尝试简化它。如果它如此复杂,您对代码的读者(包括您自己)有何期望为了以后能够理解它?也许还可以尝试将条件提取到一个单独的函数中?我相信,函数也可能没有副作用,但仍然不是纯函数。但是编译器会检测纯函数并在这种情况下对其进行优化吗?@heishe什么是纯函数,如何检测它?是的,编译器编译器将进行优化,主要是通过函数内联来简化复杂表达式。@heishe我确信有一部分编译器具有纯函数的固有概念,可以实现这一点。但这肯定不是大多数主流编译器的功能。