static_assert 编译期断言 基本上写C++模板不需要调试,因为……根本没法调试。你得把自己的大脑想象成编译器,模拟模板实例化,参数推导,模板匹配,递归调用等等,对于简单的模板当然很容易,但是对于像lambada这种复杂的模板,即便是自己写的功能简单的,也没那么容易了,看着一堆编译错误用大脑模拟编译器,只有一个感觉,痛不欲生。虽然当年看《C++ Template》《Modern C++ Design》等书跟看小说一样看得津津有味,可是像编译模板这种自虐的行为实在不是好玩的。原因在于,模板实例化都是在编译期发生的,没有办法在此期间检查模板参数以及其他状态,不能在错误刚出现时就停止并通知,只能等错误不断传导直到发生编译错误,这时的编译错误信息就很难理解并根据它找到错误点了。由衷地敬佩那些实现Loki和Boost的牛人们,简直不是人,是神。其实Loki和Boost提供了编译期检查断言的功能,只是由于天然的限制,不能提供用户自定义错误信息,而且会产生类型污染,因此用起来也不太好用。总的说来,写C++模板库基本上相当于原始人赤手空拳的捕猎猛犸象,基本上不是超人的话任务很艰巨。现在VC终于大发慈悲,提供了static_assert这个强有力的武器,对于Non-type模板参数,可以做边界条件检查(大于小于什么的),对于普通模板参数,可以使用traits技巧来检查类型属性,可以指定错误信息。不过不要期望太高,这个强有力的武器,基本上相当于一条木棒,毕竟从赤手空拳到手持木棒也算是个质的飞跃了。 我做下梦,理想的模板开发环境是,编译器支持编译器调试,设一个断点,编译器编译到这部分代码时,进入调试状态,可以看到模板的参数类型,参数推导,当前匹配的模板等信息,还有类似调用栈的从外层模板到内层模板的全部信息…… 这样的话就基本相当于AK-47加枪榴弹了,牛逼大了。
auto 自动类型 这个简单,就是用auto声明的变量会在第一次赋值时自动指定它的类型,尤其当和模板类一起使用时,用来保存返回的任何类型的值,相当方便,代码看起来也更简洁。而且依然是类型安全的。
rvalue reference 右值引用 这个功能看上去平淡无奇,初看不知所云。不要被它低调的外表欺骗,这其实是一个划时代的语言特性,我个人以为,它的重要性大于以上所有功能总和,因为它代表的是更广大开发者的利益,更普遍的性能提升,并不花哨,但是实惠。 RVO和NRVO解决了堆栈内临时对象拷贝问题,而右值引用又进一步在很大程度上解决了其他临时对象拷贝效率问题,C++爱好者终于可以扬眉吐气了。右值引用可以让我们区分操作对象是否是临时生成的对象,使用完毕后可以将临时对象的资源回收利用,而不必拷贝一份,从而提高效率。虽然临时对象并没有减少,但是由于可以选择回收利用临时对象内部的资源因而极大地减少了创建新对象的开销,也就是说可以实现从Copy到Move的进化。有了它,负责任的C++程序员们再也不必对在运行时神出鬼没的各种重型临时对象而忧心忡忡,脑子里想着有多少内部资源被无谓地复制而后销毁,我们通过右值引用取得了绝对控制权。我们在实现自己的类的时候可以利用右值引用充分复用内部资源,从而提高效率。更激动人心的是,stl里的很多对象也利用右值引用实现了move语义,我们可以大大方方地在函数里返回一个有百万个元素的vector而不用担心它的拷贝效率,欧耶!相比之下,右值引用带来的另外一个功能完美转移参数就不那么重要了。 注意,网上流传的那个用swap两个int的例子来说明右值引用的作用实在是误人子弟,基本胡扯。还是直接看Visual C++ Team Blog 的文章吧: