VC2010横空出世 C++0x初露锋芒

VC2010横空出世 C++0x初露锋芒

 

http://blog.sina.com.cn/s/blog_6e7c56670100o8d9.html

 

作为一个忠诚的C++铁杆粉丝,看着VC++沉寂多年后突然发飙,我感到很欣慰,老泪纵横,唏嘘不已... 多年来广大C++开发者们翘首企盼的激动人心的功能终于粉墨登场。

Variadic Templates 变参模板
    没有变参的年代为了实现支持不同参数数目的模板,简单的方法是最多支持N个参数就写N个template,但是会造成代码重复,难以重用,于是一些牛逼的人发明了著名的TYPE_LIST模板技术,利用模板参数推导和递归匹配实现类似变参的神奇功能。如今终于在语言级别提供了一个相当于TYPE_LIST模板类的功能,编译器终于不用在复杂的一层一层又一层的TYPE_LIST模板里来回折腾了。
    模板方面还有一个小改进就是使用"template template parameter(挺绕口的)" 时终于可以丢掉尖括号中间的空格了,编译器终于学会了根据上下文区分零距离排队的尖括号们的语义了。一些缺德的C++题就考这个知识点,也难怪,你要不小心少敲那一个空格,编译器莫名其妙的出错信息会让你郁闷半天。

Lambada 匿名函数
    在很多其他语言里早已普及的lambada也首次在C++亮相。虽然牛逼闪闪的Boost早已用出神入化的模板技巧实现了类似的功能,但是语言级别的支持无疑要强大很多。基本上stl里的算法类是匿名函数的主要客户了,再也不用自己实现一个functor类再传入算法函数里了。看上去很花哨,但这也是一把双刃剑,不恰当的使用也会有代码重复,可读性以及可维护性的问题。正因为是匿名函数,如果里面实现了复杂点的功能,别人很难知道这个玩意到底是干吗的。而如果强迫实现一个functor类,就算不写注释,起个恰当的名字也能说明功能。而且因为stl里提供了一些常用算法功能的functor类,如果可以自己写lambada的话,很多人会图省事而不去使用已有的functor,不利于以后项目维护。所以从软件工程角度看,这个花哨的功能很有可能是弊大于利。我猜说不定编译选项可以禁用lambada。我个人以为,基本上花哨的意义大于实用。

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 的文章吧:

 

你可能感兴趣的:(VC2010横空出世 C++0x初露锋芒)