函数副作用是指函数在正常工作任务之外对外部环境所施加的影响。具体地说,函数副作用是指函数被调用,完成了函数既定的计算任务,但同时因为访问了外部数据,尤其是因为对外部数据进行了写操作,从而一定程度地改变了系统环境。函数的副作用也有可能是发生在函数运行期间,由于对外部数据的改变,导致了同步运行的外部函数受到影响。1
简述所谓函数副作用是指,当调用函数时,被调用函数除了返回函数值之外,还对主调用函数产生附加的影响。例如,调用函数时在被调用函数内部:
·修改全局量的值;
·修改主调用函数中声明的变量的值(一般通过指针参数实现)。
函数副作用会给程序设计带来不必要的麻烦,给程序带来十分难以查找的错误,并且降低程序的可读性。例如,由于双目运算的两个运算分量的计算次序不同,而带来运算结果不同,就是由函数副作用引起的。对函数副作用的看法与对GOTO语句的看法一样,在程序设计语言界一直有分歧,有人主张保留,有人主张取消。探测认为,可以保留函数副作用,但是应该限制程序员尽量不要使用函数副作用。由于函数副作用的影响,会产生以下问题。
·会使双目运算的结果依赖于两个运算分量的计算次序;
·还可能使某些在数学上明显成立的事实,在程序中就不一定成立。2
表现从语言的函数设计可以看到,函数能够无条件访问全局数据(包括全局变量、全局数组、全局静态数据),通过指针或引用参数访问主调函数的栈数据或者属于程序整体的堆数据,甚至系统全局堆数据。函数副作用正是通过函数访问这些数据所表现出来的。
1、良性副作用
通过指针或引用参数设计的函数,都具有访问外部数据的倾向。或许可以利用某个函数对外部数据的修改,简化或免于后续计算的工作。例如:
//=================//X0 814.cpp//函数副作用(模拟库函数gets)//==========#includeusing namespace std;//----------------int len; //串长//----------------char* getStr (char*s) {len=0;while(cin>s [Len]&&s[len])len++;return S;}//----------------int main() {char a[100]jcout