熟悉我的朋友都知道我对Template C++的推崇,因为Template带来的更强大的抽象能力,这种爱好也就反应在了C++和大量使用了模板的STL库上。所以我很愿意听到Temlate C++在效率上打败C的例子,尤其是C并不是一门拥有丰富的描述、约束与组织对象的能力的语言。
最著名的例子是C++中std::sort如何打的经典的qsort满地找牙,这个例子也是Strustroup引以为豪的。国内有很多人也在进行这个测试,从std::sort某些版本算法的不同,到类型、inline、回调方式带来的性能差别,多方面分析了这个问题,我们从这些对比中,可以看出模板的很多优点。
最近看了一个老外叫板std::sort,号称他修改过的Qsort比std::sort快100倍。我的第一反应是不可能,细细看下去,他写的例子确实是这样。因为在vector<SomeClass>这样的容器中排序处理对象时,会大量的构造和析构,甚至还有分配内存。读到这里,我想了解C++的读者立马可以反映出问题所在,心里不是在想“菜鸟”,就是在想“故意找茬”。
我当时就是这么想的。不过出于我的习惯和直觉(长期以来它们是我最好的工具),我还是继续看下去了。果不其然,很多人的回复中,使用了比如auto_ptr这样的东西代替。我当时就想,使用auto_ptr这位难道又一个菜鸟,了解STL的不知道多少人反应和我一样?:) 当时,另一个盖楼的就说,auto_ptr是不能用在container中的。
结果这哥们是卖了个假破绽,他的代码,auto_ptr并没有直接放入vector,而是类里的成员;这样虽没有免除构造的开销,但通过Copy构造,他免除了分配内存的开销。如此,std::sort和那个LZ的Qsort就打成了平手。
看到这里,我以为这就结束了,那位找碴的不可能再有什么蹦头。让人大跌眼镜的是,LZ的真正的论点到现在才显山露水,他就这座楼前面auto_ptr等问题吹响了冲锋号,看看这语气(:
原文 Wow, I thought you guys believe std::sort can sort ANY data type because it is type safe.没错,我看的很多文章里,包括一些我很佩服的C++高手,提到std::sort的优点时都免不了提到类型的因素。
原文 Now, I see, if the object you sort contains an auto_ptr, std::sort() does not work. So what other stuff std::sort() can not sort?And surprise, surprise, surprise! I can use Qsort to sort any class objects that contains auto_ptr without a problem!!!
当然,auto_ptr有其本身的设定,谁也不会真的拿它这么玩,但这确实是一个非常明确的反例。 他总结了两种情况,依赖于内存位置的,不依赖于内存位置的。auto_ptr属于后者;对于前者,原话比较多,就不转述了,其大概意思是:如果我们想让内存中的数据按照一定方式排列,而不仅仅是其索引(指针可以理解为一种索引)或引用被重新排序,std::sort只能心甘情愿的服输。
原文 It's beginning to show that Qsort() has a much wider fit-for-use domain than std::sort() does.我不得不承认,以我的C++水平是找不出反驳的理由来,我暂时能想到的只是,我道听途说的C++ 0x对move语义的实现,能不能改善这一点;或者,使用池化一类的手段?总而言之,即便有解决方法,我认为也是要付出一定代价的。而这个辩论也到此告一段落,后面虽然有回帖,却没有真正的有力的反驳了。只有一个作者提到,std::sort只是一个specification,而不是实现,这根本不该比较。
也许我们可以针对这位老兄提到的问题做另一个sort的实现,也许这个问题确实有解决方法,我也希望C++高手能指点一二。不过仍然是我的风格,有些多余的话要说。这个帖子已经是02年的超级大“铁锅”了,可我相信不少C++程序员,都没有像这位老兄一样深入过这个问题的方方面面。我相信,参与了这个争论的,其它的那几个认为自己“更了解C++”的老外,虽然不见得一定被拍晕了,但收获是一定有的。这就有两个方面:
1. 我们自己是不是真的把问题的方方面面都考虑到了?
2. 盲从
3. 讨论的风格应该是什么样的。
对于第一个问题,我的理解是,谨慎、谨慎、再谨慎;再这个基础上,我们也没有什么别的办法。这是因为,我们没有碰到那个需求,没有得到启发。这也没什么可怪罪的,只是对一个结论所导致的设计、实现,未来使用的场景要做一个预测;无法预测的,只有在设计上就预留替换它们的空间了。当然,如果是随时能重写的东西,这就等于拥有了替换的空间,也就没有想太多的必要。总之在成本可以接受的范围内,还是应该尽人力所能的,这是一个负责任的态度。
Update:反思一下,对这个问题我又有了更深入的思考。我接触过的C++项目,基本上总会存在和内存位置相关的应用;回忆当时,自然而然的,我不会选择STL来处理它们。也就是说碰到需求时,只要我们正确的认识不同的情况,是可以做出相应的判断的。
第二个问题,不幸的,虽然鄙人一向喜欢特立独行哗众取宠,这一次却不得不承认,在这个问题上,我只是被动接受了std::sort如何如何好的那些理由;这些都是大师、专家们说的,对于一天到晚叫嚣“掌握一个东西最关键的是知道它哪儿不好”的我来说,这可够丢人的。不过我可以拉大家垫背,如果不是那么多传声筒,即使我再不动大脑,也早就听到不一样的声音,知道来龙去脉了。但是我们真的能用别人也如何如何,这种从小就说惯了的台词来安慰自己吗?
Update(接上面):当我看到std::sort比qsort如何优秀的文章时,我却没有将我的经验和这个话题联系起来,这是一个真正的MISS。也许这对我的工作没什么影响,不过从我自己来看,如果能继续加强不断的找茬挑刺的习惯,对清晰化脑子里的知识和思路还是有用处的。
最后一个问题,这个我不想说太多了,总之我喜欢刺头,比如老赵最近似乎又爆发了,哈哈。不过还是那句话,我希望技术社区带给咱们的,不仅仅是工作时间还可以忙里偷闲,更多的应该是通过交流取得进步。还有就是论战也可以搞得有技巧一点,峰回路转,比较有乐趣吧,语气可以挑逗,但不要过了界。就是这些了。
Update(继续):当我们传播一个观点时,如果忽略了其背后的隐藏假设等相关情况,这样的交流从长远来看,甚至有负面的效果。对于一个沟通无极限的时代,如果打算发出声音,这就是不得不慎重的了。
最后给出原来的战场: