比如非常常见的数学函数,例如sin,cos等等...编译器是否意识到它们没有副作用并且能够将它们移动到外部循环?例如
// Unoptimized
double YSinX(double x,int y)
{
double total = 0.0;
for (int i = 0; i < y; i++)
total += sin(x);
return total;
}
// Manually optimized
double YSinX(double x,int y)
{
double total = 0.0, sinx = sin(x);
for (int i = 0; i < y; i++)
total += sinx;
return total;
}
Run Code Online (Sandbox Code Playgroud)
如果他们可以,有没有办法声明一个函数没有副作用,因此可以安全地以这种方式进行优化?VS2010应用程序的初始分析表明优化是有益的.
另请参阅这个相关的问题,这个问题很接近但不能完全回答我自己的问题.
编辑:一些很棒的答案.我接受的那个基于它作为答案本身引起的评论,特别是链接的文章,以及在errno设定的情况下(即副作用)可能不会发生提升的事实.因此,在我正在做的事情的背景下,这种类型的手动优化似乎仍然有意义.
pure是一个函数属性,表示函数不会修改任何全局内存.
const是一个函数属性,表示函数不读取/修改任何全局内存.
鉴于该信息,编译器可以进行一些额外的优化.
GCC示例:
float sigmoid(float x) __attribute__ ((const));
float calculate(float x, unsigned int C) {
float sum = 0;
for(unsigned int i = 0; i < C; ++i)
sum += sigmoid(x);
return sum;
}
float sigmoid(float x) { return 1.0f / (1.0f - exp(-x)); }
Run Code Online (Sandbox Code Playgroud)
在该示例中,编译器可以将函数计算优化为:
float calculate(float x, unsigned int C) {
float sum = 0;
float temp = C ? sigmoid(x) : 0.0f;
for(unsigned int i = 0; i < C; ++i)
sum …Run Code Online (Sandbox Code Playgroud) 受此问题的启发,关于编译器是否可以优化掉对函数的调用而没有副作用.假设我有以下代码:
delete[] new char[10];
Run Code Online (Sandbox Code Playgroud)
它没有任何用处.但它有副作用吗?堆分配后立即释放被认为是副作用吗?