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我确信有一部分编译器具有纯函数的固有概念,可以实现这一点。但这肯定不是大多数主流编译器的功能。