7.4 本章小结
本章重点讲解了3个C++11中会给用户带来思维方式上转变的的特性:nullptr、=default/=deleted以及lambda函数。
nullptr这个新特性主要是用于指针初始化,C++11标准通过引入新关键字nullptr排除字面常量0的二义性,使之成为指针初始化的标准方式。nullptr可以安全地转换成各种指针,这使得nullptr使用简便,而nullptr不能转换为除指针外的任何类型的特性,又使得使用nullptr具有高度的安全性。程序员只需要简单将以前使用NULL的地方换成nullptr就可以在C++11编译器的支持下获得更佳的、更健壮的指针初始化代码。
而default/deleted函数则试图在C++缺省函数是否生成上给程序员更多的控制力。通过显式缺省函数,我们可以保证自定义类型符合POD的定义,而通过显式删除缺省函数,我们可以禁止class的使用者使用不应使用的函数。不过除去C++默认提供的缺省函数外,C++11标准给予了显式缺省和显式删除更多的能力,比如生成一些并非默认提供的函数的缺省定义,或者禁止一些不必要的隐式类型转换。程序员甚至可以通过删除一些函数来完成编译时期的内存分配的检查。在这样的新特性的支持下,程序员尤其是类的编写者可以更加轻松地保证写出来的类具备所需的特性。
相比于之上两个新特性,lambda对于C++程序的编写具有更大的冲击力。
早在C++98时代,程序员会喜欢使用简单的STL部件,如容器等。而使用STL的算法(algorithm)的用户相对较少。这一方面固然是由于学习难度较大、简单的算法都可以手工实现造成的,另外一方面的原因则是由于STL的算法大多数是依赖于迭代器、仿函数这些较为高级概念造成的。尤其对于仿函数,用户自定义的仿函数需要遵循规则才能被重用。而使用STL自带的各种各样的仿函数使用范围和方式过于受限,也使得STL良好设计算法的由于“不接地气”而推广受限。
lambda被设计出来的主要目的之一是简化仿函数的使用,虽然lambda的语法看起来不像是“典型的C++”的,但一旦熟悉了之后,程序员就能准确地完成一个简单的、就地的、带状态的函数定义。虽然lambda可以跟仿函数的概念一一对应也实际由仿函数来实现,但理解lambda显然比仿函数更加容易。即使没有学习过仿函数的程序员也可以轻松接受lambda。这样一来,lambda的出现必然导致STL设计、使用方法上的改变,但其最终意义是让更多的程序员无困难地使用STL的各种调优后的算法,真正享受STL的全部力量。
此外,lambda作为局部函数也会使得复杂代码的开发加速。通过lambda函数,程序员可以轻松地在函数内重用代码,而无需费心设计接口。事实上,曾经出现过一般重构的风潮,在那段时期,C++程序员被建议为任何重用的代码创建函数,而lambda局部函数的到来则带来了理性思考和折中实现的可能。当然,lambda函数的出现也导致了函数的作用域在C++11中再次被细分,从而也使得C++编程具备了更多的可能。
以上种种或许是C++早就应该做到的,但一直未能实现,现在终于在C++11中,lambda让我们看到了新的光芒。