## 回避 C 指针是要付出代价的
在 C 语言中,在执行这些基本原则时,指针是最简单明快的工具,像是著名厨师庖丁手里的刀。在静态类型语言中,任何企图回避指针的行为,必然会导致编程语言的语法复杂化或者削弱语言的表达能力。
在 C++ 中为了回避指针,发明了引用——本质上一种被弱化了的指针,结果导致 C++ 初学者经常要问『什么时候用指针,什么时候用引用』这样的问题。在智能指针未问世之前,STL 提供的泛型容器无法存储引用,为了避免在容器中存储对象时发生过多的内存复制,往往需要将指针存到容器中。当某个函数在内部创建了一个比较大的对象时,这个函数想将这个对象传递给其他对象时,这时如果不借助指针,那只能是将这个大对象作为返回值,然后引发了对象数据不止一次被复制的过程。如果在函数中 `new` 一个大对象,然后以指针的形式将其返回,这又与 C++ 一直想向用户掩盖指针的理想发生了矛盾……为了解决这个问题,终于在 C++ 11 里搞出来一个挺复杂挺扭曲的右值引用的办法,解决了在类的复制构造函数中偷偷的使用指针,但是类的用户却看不到指针这样的问题……
Java 回避指针的策略比 C++ 要高明一些。在 Java 中,即没有指针也没有引用。只要是类的实例(对象),无论是将其作为参数传递给函数,还是作为函数的返回值,还是将其复制给同类的其他对象,都是在传地址,而不是在传值。也就是说,Java 将所有的类实例都潜在的作为指针来用的,只有那些基本类型才是作为值来传递的。这种对数据类型进行了明确的区分的态度是值得点赞的,但是当 Java 想将一个函数(方法)传递给另一个函数(方法)时,代码就出现了扭曲,完全不能做到像 C 语言以指针的形式传递函数那样简洁直观。
C# 在指针的处理上似乎要比 C++ 与 Java 好得多,但是将那些使用指针的代码标定为 `unsafe`,这是一种歧视。类似于『嗟,来食!』。廉者不受嗟来之食。
在动态类型语言中,例如 Python,据说是一切皆引用,这样很好。也可以直接将一个函数作为参数传递给另一个函数,甚至还能在一个函数中返回一个函数,这样更好。动态类型语言在语法、抽象能力、类型安全以及资源管理方面很大程度上超越了 C、C++、Java 这些静态类型语言,但是用前者编写的程序的计算速度却往往比后者慢上一倍。
没有完美的指针,也不会有完美的编程语言,这一切皆因我们是在机器上编程,而不是在我们的大脑里编程。