在主流的编程语言中,函数是构成程序的最小单元,如果把编程比喻成搬砖那么函数就是砖。搬砖是一门大学问,大多数人搬不好。写函数是更大的学问,许多程序员都写的很糟糕,包括我自己。
今天说说函数编写的错误集锦,怎样写函数会让函数变的特别糟糕,函数的传参在编译器中是如何优化的。
先执行一段代码:
1 | //初始化一个10万的数组 |
要讲的原理与语言无关,这里 var_dump()
是打印函数 memory_get_usage()
是获取程序当前的内存使用情况。
运行结果:
1 | 数组消耗:int(4593512) |
这段代码执行了cp()
函数,并且申明了一个大数组,但是内存没涨(其实涨了32,这也是个有趣的问题,与当前要讲的内容无关,之后单独讲讲)。这是为什么?
在很多年以前,函数中如果要传递数组,编译器会先把数组复制一份,再把复制好的数组传给函数。这样做了一段时间之后发现如果数组太大并且在函数中只读的话复制是没意义的,还特别浪费内存。然后就在编译器中加了一种机制叫『写时复制』,简单理解就是当函数内部要对数组做修改时才会把数组复制一份。
这是函数内部的一种优化方式,在编译器内部很多场合都用到了这种优化方式,下面看代码。
1 | var_dump(memory_get_usage()); |
运行结果:
1 | 初始内存:int(395680) |
只加了一行代码,在函数中对数组做了修改(写操作),于是内存消耗就涨了一倍。
『写复制』在大多数情况下能帮助我们节省内存,如果程序员不知道这个原理,频繁的在函数中对数组进行写操作,会导致代码消耗内存严重,执行效率低下。虽然肉眼看不出程序哪里有问题,而且运行结果也符合预期,但是这不是一段好代码。
这段代码我们应该如何优化呢?
1 | var_dump(memory_get_usage()); |
只需要改一行,改完之后效果如下:
1 | 初始内存:int(395688) |
同样的『写时复制』这里却没触发,这是为什么?请各位思考,下周讲原理