Can/do编译器简化了涉及函数的逻辑表达式
Can/do compilers simplify logical expressions involving functions?
一些计算布尔值的函数:
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();
}
由于函数可能有副作用,因此不能以任何方式"优化"条件,因为所有函数都必须以良好定义的方式(有条件地)调用。
如果你想优化,你可以先把结果赋值给变量:
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()
永远不会执行,即使用户明确地尝试这样做。这个可以并且将会导致bug。
既然你的前提是有缺陷的,不,他们不会。
(a()&&b()&&c()) || (a()&&b()&&!c())
绝对不能重写为(a()&&b())
C(和c++)不是函数式编程语言(像Haskell)
但问题是,一般来说,它不能以这种方式重构 !
如果任何函数都有改变c()
结果的副作用,那么第二次调用可能会返回与第一次不同的结果。
不仅如此,由于短路执行,事情可能会变得更加混乱。
在C语言中,函数的返回值通常给出了函数是否成功执行。例如调用图形例程,转换文件。想想你有多频繁地使用指针来改变函数外部的东西。或者调用另一个输出的函数。有人说这不是函数式编程。
如果编译器能够确定foo()变化而不做任何事情,那么它可能会通过各种方式简化它,但我不会指望它。
下面是一个非常简单的例子
bool foo()
{
std::cout << "this needs to be printed each time foo() is called, even though its called in a logical expressionn";
return true;
}
int main()
{
if ((foo() && !(foo()) || foo() && !(foo())))
return 0;
return 1;
}
编辑任何布尔代数的变量都应该简化。
相关文章:
- C++模板函数中的初始化 - 新的初始值设定项表达式列表被视为复合表达式
- 来自 DLL 的函数调用 [表观调用的括号前面的表达式必须具有(指向-)函数类型]
- 在函数中使用 const int size 参数创建数组会在 Visual Studio 中抛出错误 C++:表达式的计
- 表达式 SFINAE:如何根据类型是否包含具有一个或多个参数的函数来选择模板版本
- 函数返回的 rvalue 引用(表达式)是 xvalue - 但没有标识?
- 折叠表达式和函数名称查找
- C++:带有大括号初始化列表的函数调用表达式 - 标准是否规定在单个元素列表的微不足道的情况下忽略大括号?
- 不是 lambda 函数中的常量表达式
- 保证逻辑 AND 表达式中的函数调用
- std::cout 在打印变量与函数表达式时的行为不同
- C2276 '&':对绑定成员函数表达式的非法操作
- 函数表达式的字符串转换,带有 Catch 断言中的参数
- 为什么返回非引用类型的函数表达式被认为是prvalues而不是xvalues
- 定义函数时,哪种类型是lambda函数/表达式
- '&' :对绑定成员函数表达式的非法操作
- 如何解析和调用c++类函数表达式
- "&":对绑定成员函数表达式的非法操作。从关键点矢量 OpenCV 获取容量
- 如何使boost-proto函数表达式可流化
- "!"绑定成员函数表达式的非法操作
- lambda 函数/表达式是否支持 constexpr