刘未鹏|C++的罗浮宫

Knowledge sharing is the best reuse

用户操作
[即时聊天] [发私信] [加为好友]
刘未鹏ID:pongba
959232次访问,排名30好友45人,关注者228
兴趣:人工智能、机器学习、知识发现,认知科学。
pongba的文章
原创 105 篇
翻译 8 篇
转载 0 篇
评论 1818 篇
刘未鹏的公告
除非特别声明,本站采用Creative Commons License许可。转载请保留作者、出处。非商业。

FeedSkyFeedBurner
或者用 鲜果 GR 抓虾 订阅。

CSDN Blog暂时不支持RSS全文输出,对此感到不便的朋友可以使用强大的greasemonkey脚本:GReader Preview Enhanced(链接),该脚本支持在GReader里面直接打开全文页面。

我经常出没于TopLanguage讨论组

我的豆瓣TwitterDelicious

《C++的罗浮宫》5年选集

——知识分享是最大的复用

下载地址:csdn资源频道|mediafire

讨论问题请到TopLanguage小组

TopLanguage


gtalk/msn(邮件请发送到gmail邮箱)

pongba@gmail.com
pp_liu@msn.com

搜索C++的罗浮宫上的内容(不要回车,点击Go)

twitters

books I've translated




这个Blog上都写了哪些东东

最近评论
shupan:非常感谢你的文章,在看你的文章时, 我发现有很多类似的事情发生在我的身上。
kewan001:我也时不时的思考,关于如何学习,记忆等这些问题,但不曾看过什么著作,你带我看到了一个新的世界,谢过
biermando:收藏!
chenxiaoshun:恐怕是我在CSDN所看过的最好的文章。
xuxiandi:佩服啊。。。敬仰中。
文章分类
收藏
相册
其它图片
文章中的图片
我的大头贴
C++
Andrei Alexandrescu
Andrew Lumsdaine
Bjarne Stroustrup
boost
C++ Standard Commitee
Doug Gregor
Hans J. Boehm
Jaakko Jarvi
Jeremy G. Siek
Matthew Wilson
newsgroups
boost.Developer
boost.User
comp.lang.c++.moderated
comp.std.c++
TopLanguage
Open Source
Ant
codeplex
Danga
Google AJAX Search API
Google Code Prettify
Google Web Toolkit
Hadoop
MS shared source initiative
notepad++
STLSoft
不认识的朋友们
fatalerror99
Glacier
realazy
SpiritEpic
TK
Yelz
丁丁虫
冰云
刘慈欣
卢昌海
吴欣安(atppp)
姬十三
林达华
浦宇平
程化
阮一峰
高远
鲍盛
机器学习/数据挖掘/信息检索/自然语言处理/认知科学/人工智能
AAAI
arXiv
Charles Kemp
Christopher Bishop
Christopher Manning
Cognitive Daily
Dan Jurafsky
David MacKay
ECML PKDD
Geoffrey Hinton
Herbert Simon
ICML
IJCAI
Jeff Hawkins
Jiawei Han
JMLR
Josh Tenenbaum
Larry Wasserman
Lucene
Marvin Minsky
MIT AI Lab
MIT Computational Cognitive Science Group
Mitchell Marcus
ML
NetLab
NIPS
Peter Norvig
Stanford AI Lab
Stanford NLP Lab
Stephen Boyd
Tom Mitchell
Trends in Cognitive Science
Vladimir Vapnik
Weka
Zhihua Zhou
其它
Gigapedia
Scientific American
Scientific American Mind
科学松鼠会
科幻世界
认识的朋友们
alai
chenyufei
dd
DreamHead
duguguiyu|Venus神庙
Googol
Joyfire
littlestone
lxwde
Matrix67
realfun
RiceBall@cnBlogs
RiceBalll
roofalison
soloist
Tinyfool
windstorm
YongSun
书剑
云风
余晟|乱象&乱想
冯大辉(Fenng)
刘新宇
刘江@图灵
史晓明
周星星
周筠@博文视点
孟岩
张志强|阅微堂
张振
徐宥|4G Spaces&Web 2.3
方舟@博文视点
曾登高
李笑来|Pure Pleasure
杨文博
熊节
王信文|地球没有好朋友
王康生
荣耀
莫华枫
蒋涛
袁泳(g9)|负暄琐话
许式伟
谢东升
谷文栋|Beyond Search
陈冀康@华章
陈怀兴
鲍志云
存档
订阅我的博客
XML聚合  FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
订阅到BlogLines
订阅到Yahoo
订阅到GouGou
订阅到飞鸽
订阅到Rojo
订阅到newsgator
订阅到netvibes

原创 为什么C++收藏

新一篇: 为什么C++(中文版——感谢waterwalk翻译) | 旧一篇: 《C++0x漫谈》系列之:瘦身前后——兼谈语言进化

Why C++

 

刘未鹏(pongba)

C++的罗浮宫(http://blog.csdn.net/pongba)

 

非常感谢waterwalk翻译了整篇文章,我整理了之后单独贴了出来,见这里

 

The Problem

So, why C++? Before you frown and turn away. Just try to answer this simple question.

 

Efficiency, right? Everybody knows the answer. But as it turned out, when discussing a programming language or everything related to one, one should be very specific. Now why’s that? Let me ask you another question: if efficiency is the only reason people use C++, then why don’t they just use C? C is admittedly more efficient than C++ (yeah, yeah, I know it has been proved that C isn’t to any significant extent more efficient than C++, so don’t get me wrong here, because even if they are equally efficient, the problem still exists).

 

The Myth

I know you are going to say “better abstraction mechanism”, because after all C++ is designed to be a better C, one that has uncompromised efficiency and yet at the same time has all those fancy high-level features. But then the problem comes down to “does it really matter if the developers need those fancy features?  I mean, after all we all have been hearing voices about KISS and stuff, and we all have heard about the claim that, compared to C++, C is more KISS so we should use C. This unstoppable argument has turned the comparison between C and C++ into a big myth (or maybe a mess). And surprisingly, it seems that many people do incline to C, the reason mostly being that C++ is so hard to use right. Even Linus thinks so, too.

 

The real serious impact of this phenomenon is that it drives more people to C when they’re weighing their options, be them C and C++; and once they start using C, they will soon get satisfied and comfortable with what suffices, experiencing what is called “satisfaction”. This is when they will come out and claim that C actually is a better choice than C++ even though they didn’t actually try to use C++ or they aren’t adequately good C++ programmers at all. The real answer, however, almost always begins with “it depends”.

 

So, did I say “it depends”? On what? Obviously there’re some areas where C is a better choice than C++. For instance, device driver development is usually something that doesn’t need fancy OOP/GP techniques. It’s just simple data manipulation; what really matters is the programmers know exactly how the system works, and what they’re doing. Now what about OS development? I’m not a guy who’s been involved in any kind of OS development myself, but having read a fair amount of OS code (Unix mostly), I’ve come to feel that there’s a significant part of the OS development that doesn’t need OOP/GP either.

 

However, does that mean that, in all those areas where efficiency matters, C is a better choice than C++? Not really.

 

The Answer

Let’s do this case by case.

 

First of all, when people are concerned about efficiency, there’re really two kinds of efficiency – time efficiency (e.g. OS, runtime, real-time applications, high-demanding systems) and space efficiency (e.g. all sorts of embedded systems). However, this categorization doesn’t really help us determine whether we should use C or C++, because C and C++ are both extremely efficient as to both time and space. What really affects our language choice (between C and C++, of course) is the business logic (here by “business”, I don’t mean the “enterprise application business”). For example, is it better to use OOP/GP to express the logic or is it better off being kept pretty much just about data and procedures.

 

From this point of view, we can vaguely divide applications into two categories (of course, with the premise that what we’re concerned with is C/C++, not java/c#/ruby/erlang etc.): low-level applications and high-level applications, where low-level applications means the ones where fancy abstractions such as OB/OOP and GP are pretty much of no use, and high-level means all the rest. Now, obviously, of all the areas where C/C++ is used (because of their high-efficiency), there’re a significant number of “high-level” applications (see those listed on Bjarne Stroustrup’s homepage), where abstraction is just as important as, if not more important than efficiency. And those are precisely the places where C++ is used and useful in a unique sense, and where C++ is a better choice than C.

 

Wait, there’s more. As it turns out, even in those areas where programmers don’t use high-level abstractions in their code per se, there might be a reason they should use C++, too. Why’s that? Just because your code don’t use class or templates doesn’t mean it doesn’t use a library that does. Considering the availability of all the handy C++ library facilities (with tr1/tr2 coming soon), I think there’s a pretty strong reason to use C++ in these cases - you can stick to the C core of C++ when coding (KISS in any way you want), and at the same time you’ve got some awesome C++ libraries at your disposal (e.g. STL containers and algorithms, tr1/tr2 components, etc.). And finally, there’s this one thing that’s always ignored by many people – sometimes KISS relies on abstractions. I think Matthew Wilson made a crystal clear point about this in the prologue of his new book “Extended STL, Vol 1”, where he laid down two blocks of code, one written in C and one in C++:

 

// in C

DIR*  dir = opendir(".");

if(NULL != dir)

{

  struct dirent*  de;

  for(; NULL != (de = readdir(dir)); )

  {

    struct stat st;

    if( 0 == stat(de->d_name, &st) &&

        S_IFREG == (st.st_mode & S_IFMT))

    {

      remove(de->d_name);

    }

  }

  closedir(dir);

}

 

// in C++

readdir_sequence entries(".", readdir_sequence::files);

 

std::for_each(entries.begin(), entries.end(), ::remove);

 

And it’s even simpler in C++09:

 

// in C++09

std::for_each(readdir_sequence(".", readdir_sequence::files), ::remove);

 

I think this is exactly the reason why one should use C++ even in those cases where he doesn’t really need class or templates in his own code – the handy C++ libraries he will find very useful does. Similarly, if an efficient container (or a smart pointer) will save you from all the boring job of manual manipulation of memory, then what’s the point of using the primitive malloc/free? If a better string class (I’m not talking about std::string; everybody knows it’s not the best C++ can do) or regex class  can relieve you of all the cluttered string-manipulation code you don’t even want to look at, then what’s the point of doing it manually. If a ‘transform’ (or a ‘for_each’) can do your job in one line so succinctly and clearly (and I know, of course, C++ need lambda function support for those – that’s what C++0x is for), then what’s the point of hand-written for-loops? If high-order function is really what you need, then what’s the point of using awkward workarounds to approach the same deal?

 

KISS doesn’t mean “primitive”; KISS means using the most suitable tool for your job, where “most suitable” means the tool you use should help you express your mind as straight (and succinct) as possible, as long as it doesn’t compromise the readability and understandability of the code.

 

The Real Problem

People might say that C++ is much more easily misused than properly-used, and C, on the other hand, is always more manageable and controllable as to complexity. In C++, an average programmer might come up with a whole bunch of highly coupled classes that degenerates fast into a big mess. But this is actually a separate issue. On the one hand, it can pretty much occur in any object oriented language. There’re always programmers who dare to write classes on top of classes even before they have any idea what HAS-A is and what IS-A is; they learn all the syntax of defining a class and inheriting one from another and they thought they’ve grasped the essence of OOP. On the other hand, the reason it appears to be more serious in C++ is because C++ has so many accidental complexities that impede the design, and because C++ is so flexible that pretty much every problem in C++ has several alternative solutions (thinking of all the GUI libraries) so that weighing all the options becomes a hard job itself. The accidental complexities are a historical baggage that C++0x is trying so hard to (and hopefully will) get rid of; the flexibility with respect to design isn’t actually a bad thing if you think about it - it helps good designers make good designs; and if someone blame them for hurting his brain then maybe it’s his problem, not the language’s; maybe he shouldn’t be the one to make a design. And if you’re so worried that your fellow C++ coders will be enticed by fancy high-level features and that your project will eventually get screwed, then maybe what you should do is setting up a coding standard and enforce it (or you can just follow the collective wisdom, or stick to the C core or C with class part of C++ if necessary), not flinching away just because there’re risks (risks that can be avoided by policies), because then you will not be able to access all the C++ libraries anymore, mind you.

 

On the other hand, there’s this more important psychological problem – if there’s a bizarreness in a language, then eventually someone will find it and people will be attracted by it, and it will draw energy from the main people effort of doing something really useful (It’s kind of like the Murphy's Law), let alone the ones that can lead to an (on some level) elegant solution to a real problem. People are inherently attracted by scarce resources. Corollary: Tricks and bizarrenesses are scarce resources, so they draw people’s attention, not to mention the fact that mastering a trick makes one feel special in the herd. The bottom line is, even useless tricks draw people’s attention so heavily.

 

How many black corners are there in C++? How many tricks are there in C++? All in all, how many accidental complexities are there in C++?

 

To be fair, most of the tricks and (you might say) techniques that have been discovered in recent years (i.e. modern C++) are driven by real needs, particularly the needs to implement highly flexible and generic library components (thinking of all the components in boost). And they did lead to (on some level) elegant solutions to real problems. Think about it this way: if you’re put in a place where either you have to use tricks to implement something really useful or you don’t implement it so other people won’t have the benefit of using it. What would you choose? I know that the boost heroes chose the former – implementing them, no matter how hard and tricky and cumbersome the implementation is.

 

But all those arguments don’t change the fact that we deserve to have a language that supports a clean way to express our minds in code. Take boost.function/boost.bind/boost.tuple for examples, variadic templates will tremendously simplify (by reducing the LOC to nearly 1/10 of the original) the implementation of the three (and many, many more to come) libraries, and the code will become succinct and as simple as possible, too. Auto, initializer-list, rvalue-reference, template-aliasing, strong-typed enums, delegating-constructors, constexpr, alignments, inheriting-constructors, etc; all those C++0x features, they all have one goal – eliminating the various accidental complexities or embarrassments of the language.

 

As Bjarne Stroustrup said, obviously C++ is too complicated; obviously people get scared and sometimes turn away. But “people need relatively complex language to deal with absolutely complex problems”. We can’t make a language more powerful by taking features away from it. Complex features like templates and even multiple-inheritance can be useful if they’re exactly what you need, you just have to use them very carefully and by necessity so that you don’t shoot yourself in the foot. Of all the complexities in C++, the ones that really get in our way are the accidental complexities (someone might call them “embarrassments”), not the paradigms the language supports (there’re only three). And that’s a very important reason why we should embrace C++0x, because it aims at eliminating the long standing accidental complexities C++ had and make obsolete all the arcane tricks (there’s absolutely huge amount of them out there; check all the C++ books and maybe the boost library and you’ll know what I’m talking about) so that we can express our mind clearly and directly.

 

The Conclusion

C++ is hard, and even harder to use correctly. So when you decide to use it, be careful, always know where you are and what you really want. Here’s a simple guideline:

 

Do we need to be efficient?

If so, then

 

Do we need abstractions in our code (think very carefully on this one, because it’s very hard to estimate whether the benefit of using the high-level features of C++ outweighs the risk of using them incorrectly; the proper answer depends on how well trained your programmers are, what coding standard you follow and how well it’s enforced, etc.)?

If so, then use C++. Otherwise,

 

Do we need good C++ libraries to ease our job?

If so, then use C++, but meanwhile always remember what you are doing – if your code doesn’t really need all the fancy abstractions, then try not to get sucked into them; don’t use class or templates just because you’re writing code in a .cpp file and using a C++ compiler.

 

Otherwise, use C, but then you might wonder why not just use the C core of C++. The same reason as always: people get easily sucked into fancy language features even when they don’t really know if they’re going to helpI can’t tell you how many times I wrote a bunch of classes only to find out “what the heck are these classes for?”. So, if you can stick to the C core or C with class part of C++ and keep simple things simple, or if your code needs a migration path from C to C++, use C++ then, but be very careful. On the other hand, if you need neither abstraction mechanisms in your code nor quality C++ libraries because what you’re doing is so simple that you don’t even need convenient components like containers or strings, or you decide that the benefit C++ can bring you in your project is minor to an extent that it’s not even worth taking the risk, or you just simple don’t have enough people that can use C++ in a proper way, then maybe you should stick to C.

 

The bottom line: keep simple things simple (but remember that simplicity can be achieved by using high-level libraries); use abstractions when necessary (and even then, make spare use of it; follow good design principles and established good practices).

 

--

我的讨论组

TopLanguage

 

发表于 @ 2007年09月11日 14:19:00|评论(loading...)|编辑

新一篇: 为什么C++(中文版——感谢waterwalk翻译) | 旧一篇: 《C++0x漫谈》系列之:瘦身前后——兼谈语言进化

评论

#dsniff 发表于2007-09-11 15:44:28  IP: 61.157.97.*
耶~!沙发!
#啊 发表于2007-09-11 18:42:15  IP: 10.0.40.*
谁翻译一下,让我等门外汉看看。
#CaiKanXP 发表于2007-09-11 19:09:41  IP: 60.190.149.*
门外汉吗,不用看了,先入门吧
#Atry 发表于2007-09-11 21:55:55  IP: 58.31.86.*
所有人都知道 C++ 大体上是 C 的超集,然而用又不敢用那些特性。心理负担啊心理负担。
这个心理负担是有道理的。
#lurenfu 发表于2007-09-12 09:13:35  IP: 218.80.241.*
Linus said: "The only really important part is the *design*."
#Semigod 发表于2007-09-12 12:47:49  IP: 137.117.2.*
I completely agree with this guy.
#Cnzhangzhen 发表于2007-09-12 13:40:25  IP: 155.56.68.*
年经帖阿,你和云风商量好的吧?
#dananhai 发表于2007-09-12 16:05:39  IP: 207.46.55.*
能不能在用国语讲一次阿
#liangshi 发表于2007-09-13 10:23:04  IP: 207.46.92.*
刘兄写了一篇令人敬畏的好文,受益匪浅!

讨论语言不能缺少具体代码。近两篇文章中代码示例都很有力:

1. KISS不是原始,是利用合适的工具完成合适的任务。C++的设计目标之一是用直观的表达(在不损失运行性能的情况下)完成指定的任务。

2. 语言、工具进化(特别是C++0x)的目标是消除偶然复杂性(非本质复杂性)。这是语言设计者、工具设计者、应用程序员都应该追求的目标。
#fastest286 发表于2007-09-13 17:25:16  IP: 61.140.126.*
今天看到一篇文章, 觉得说得不错, 贴几段出来.
文章的背景是, D 的开发者们讨论要不要给语言设计 DSL 能力, 其中一个人的意见. (BTW: 连google 里面的 C++ 开发, 都禁用 template, 可见要组织一个能协同用好C++ 高级特性的开发团队, 还是麻烦).


原文在:
http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=48357

Even companies perceived as progressive care deeply about ensuring the code is 'pedestrian' in nature. Google, for example, outlawed C++ templates. They did this because their experience showed such code was unmaintainable, more often than not. In the hands of the masses, such tools are often used for creating a language within a language, and everyone's version has a personal stamp: MyDSL

......
下面这段, 他认为应该怎么评价要不要加一个 feature, 我觉得说得有道理:

In no way am I saying "oh, all that meta-stuff is poppycock", as someone had suggested to me. I personally /like/ a touch of DSL here and there
(have been shot-down in the past for exactly that). Instead, my personal concerns (when it comes to D) are based purely around three things:

1) is it of notable or daily value to 50%+ or more of users?

2) does it further delay fixing existing features that match #1?

3) does it have /real/ potential to hinder adoption due to ignorance, religion, sexual preferences, or the weather?

Those are all arguable, of course. Programmers are notoriously fickle when it comes to #3. But my concern over that one is the commercial dev
shops; the likes of Goog
#fastest286 发表于2007-09-13 17:39:51  IP: 61.140.126.*
回帖被截断, 我贴到下面地址了.

http://groups.google.com/group/pongba/browse_thread/thread/909b80fa083d4f24
#liu_chulong 发表于2007-09-13 23:30:57  IP: 219.137.137.*
KISS doesn’t mean “primitive”; KISS means using the most suitable tool for your job, where “most suitable” means the tool you use should help you express your mind as straight (and succinct) as possible, as long as it doesn’t compromise the readability and understandability of the code.

I extremely agree with this viewpoint.
Thx, Pongba.
Also, keep simple things simple.
#Learn PHP 发表于2007-09-14 04:18:02  IP: 207.139.16.*
good post
#longshanks 发表于2007-09-14 07:35:52  IP: 58.41.31.*
禁用template的原因很简单,因为无法让一整个团队的人都能正确使用template。但问题不在template上。而是在团队组织上。
目前限于软件开发管理理论和理念,开发团队无法严格地层次划分工,让一部分开发服务性组件,另一部分使用组件。开发服务型组件的要求不同于使用者的要求。在不同层面上允许或禁止玩弄template。
这种专业化分工是已被证明的,最高效的生产方式。一个机加工厂里永远不会要求每一个工人都要会铸造,冷作,钣金,切削等工作,所有的人都专业化。开车床的绝对不能去翻砂,安全问题也就此避免了。
软件产业还在幼年时期,还需要很长的时间,才能领悟工业界百余年行之有效的方法。
#longshanks 发表于2007-09-14 07:49:53  IP: 58.41.31.*
禁用template的原因很简单,因为无法让一整个团队的人都能正确使用template。但问题不在template上。而是在团队组织上。
目前限于软件开发管理理论和理念,开发团队无法严格地层次划分工,让一部分开发服务性组件,另一部分使用组件。开发服务型组件的要求不同于使用者的要求。在不同层面上允许或禁止玩弄template。
这种专业化分工是已被证明的,最高效的生产方式。一个机加工厂里永远不会要求每一个工人都要会铸造,冷作,钣金,切削等工作,所有的人都专业化。开车床的绝对不能去翻砂,安全问题也就此避免了。
软件产业还在幼年时期,还需要很长的时间,才能领悟工业界百余年行之有效的方法。
#waterwalk 发表于2007-09-14 13:59:19  IP: 219.131.196.*
我来翻译一下吧:
问题
为什么用c++呢? 在你皱着眉头离开之前,试着回答这个简单问题。

效率,是么?人人都知道这个。但情况是,当一个人开始讨论编程语言或与其相关的话题时, 他必需要

非常有针对性。为什么呢?我来问你另一个问题:如果效率是人们使用c++的唯一理由,那么为啥不直接

用c呢?c被认为比c++效率更高(嗯嗯,我知道c没有比c++的效率高多少,所以这里别误解我的意思,因

为即使它们二者效率相同,刚才的问题依然存在)
#waterwalk 发表于2007-09-14 14:00:31  IP: 219.131.196.*
迷思

我知道你又要说“更好的抽象机制”了,因为毕竟c++是要设计成一个更好的c的。c++没有牺牲效率,同

时又添加了这么多奇妙别致的高级特性。但问题又变成了“开发者们真的需要这些高级特性么?”。 毕

竟我们一直听人讲KISS之类的东西。我们也都听到有说法声称c比c++更KISS,所以我们要用c。这种持续

不断的争论将c与c++之间的比较变成了一个大大的迷题(或者说是混乱)。令人惊讶的是,貌似的确有很

多人更加倾向于用c,最大的理由就是c++实在是太难用对了。甚至Linus也这么想。

这种现象最大的影响就是在人们在c和c++之间权衡时,使人们倾向于使用c。而且一旦人们开始用c,他们

很快就适应并满足了。于是即使他们还没有试试c++,或者他们还没成为好的c++程序员时,他们就开始声

称c比c++更好了。

那么,我说过“不一定”还是其它什么了么?显然有些领域c是更好的选择。例如设备驱动开发就不需要

那些精巧别致的OOP/GP技巧。那只是简单的处理数据,真正重要的是程序员确切地知道系统是如何运转的

,以及他们正在做什么。那么写操作系统呢?我本人并没有参与任何操作系统的开发,但我读过不少操作

系统代码(大多是unix的)。我的感觉是操作系统很大一部分也不需要OOP/GP。
#waterwalk 发表于2007-09-14 14:02:50  IP: 219.131.196.*
但是,这就表示在所有效率重要的领域,c就是比c++更好的选择么?未必。

解答

让我们一个一个来分析。

首先,当人们关注效率时,有2种效率——时间效率(例如OS,运行时库,实时应用程序,要求严格的系统)和空间效率(例如各种嵌入式系统)。但是,这样的分类并不能帮我们决定用c还是c++,因为c和c++的时空效率都很高。真正影响选择语言的因素是业务逻辑(这里的“业务逻辑”并非表示“企业应用业务”)。例如,使用OOP/GP来表达逻辑好呢,还是就只用数据和过程好呢?

据此观点,我们可以把应用程序大致分为两类(当然前提是关注的是c/c++而不是java/c#/ruby/erlang等等):底层应用程序和高层应用程序。这里底层是指象OB/OOP和GP没啥用处的地方,其余归到高层。显然,在所有c/c++应用的领域(这些领域需要c/c++的效率),属于高层的应用有很多(可以看看Bjarne Stroustrup在他主页上的列表)。在这些领域中,即使抽象至少是和效率一样重要的。
#waterwalk 发表于2007-09-14 14:03:47  IP: 219.131.196.*
等等还有。即使在程序员不需要高级抽象的领域,也还是有理由使用c++的。为啥呢?仅仅是因为你的代码中没有用类或模版并不意味着不能用以类或模版实现的库。因为有如此众多方便的c++库(还有即将到来的tr1/tr2),我觉得有充分的理由在这些领域中使用c++——你可以在编码时仅使用c++中c的那部分核心(以任何你喜欢的方式来KISS),同时还能用强大的c++库(比如STL容器、算法和tr1/tr2的组件)。

最后,人们还常常忽略了一点——有时KISS是建立在抽象上的。我觉得Matthew Wilson在他新书《Extended STL卷1》的序言中对此做了很好的阐释。他写了2段代码,一段用c,另一段用c++:
// in C

DIR* dir = opendir(".");

if(NULL != dir)

{

struct dirent* de;

for(; NULL != (de = readdir(dir)); )

{

struct stat st;

if( 0 == stat(de->d_name, &st) &&

S_IFREG == (st.st_mode & S_IFMT))

{

remove(de->d_name);

}

}

closedir(dir);

}



// in C++

readdir_sequence entries(".", readdir_sequence::files);



std::for_each(entries.begin(), entries.end(), ::remove);



And it’s even simpler in C++09:



// in C++09

std::for_each(readdir_sequence(".", readdir_sequence::files), ::remove);

#waterwalk 发表于2007-09-14 14:04:35  IP: 219.131.196.*
我认为这就是人们应该是用c++的原因,即使他在自己的代码里不需要类或模版——c++方便的库太有用了。类似地,如果一个高效地容器(或智能指针)能把你从无聊的手动内存管理中解放出来,为啥还要用那原始的malloc/free呢?如果一个更好得string类(我可没说std::string,地球人都知道那个不是最好的)或正则表达式类能把你从一陀一陀的、你看都不想看的处理字符串的代码中解脱出来,那么为啥还要手动去做这些事呢?如果一个"transform"(或"for_each")能够用一行代码把事情漂亮搞定,为啥还要手写一个for循环呢?如果高阶函数能满足你的需要,那么为啥还要用笨拙的替代方法呢?

KISS并不等同于“原始”;KISS意味着用最适合的工具来做事情,这里“最合适”的意思是工具能够帮你

以尽量直接简洁的方式来表达思想,同时又不降低代码的可读性,另外还保持代码容易理解。
#waterwalk 发表于2007-09-14 14:06:40  IP: 219.131.196.*
真正的问题

人们可能会说c++更容易被错误使用,相比而言,c对于复杂性更容易管理和控制。在c++中,一个普通程序员很可能会写出一堆高度耦合的类,很快情况就变得一团糟。但这个其实是另外一个问题。在另一方面,这种事情也很可能发生在任何一门面向对象语言中。总是有程序员在弄懂什么是HAS-A和IS-A前,就敢于在类上再写类,一层一层摞上去。他们知道如何定义类,如何继承类,然后他们就认为自己 已经掌握了OOP的精髓。另一方面,这一问题在c++中更为严重,因为c++有如此众多的偶然复杂性在阻碍设计,而且c++又是如此灵活,很多问题在c++中都有好几种解决办法(比如那么多的GUI库),于是在这些选择中进行权衡,本身就很困难。c++的偶然性是其历史包袱使然,c++0x正要努力消除(希望如此)。对于设计来说,灵活性不是个坏事情——可以帮助好的设计者作出好的设计。如果有人抱怨说这个太费脑细胞了,那可能是这个设计者本身的问题,而不能怪语言。可能就不该让他来作设计。如果你担心c++的高级特性会把你的同事引入歧途,把项目搞砸,那你也许应该指定一份编码标准并严格推行(或者你也可以遵循集体的智慧,或者在必要时,只使用c++中的c或c with class那部分),而不是因为有风险就躲开c++(其实这些风险可以通过一些策略来避免的),因为那样的话,你就没法用那些c++的库了。


另一方面,还有一个更为重要的心理因素——如果语言中存在某个奇异的特性,那么总会有人发现的,总会有人为之吸引的,然后就使人们从真正有用的事情中分心出来(有点像Murphy法则),从而使那些有可能对真正问题研究出漂亮(在某种程度上)的解决方案的人们孤立起来。人们本性上容易受到稀有资源的诱惑。结果,奇技淫巧是稀有资源,然后就吸引了人们的注意力,更别说掌握一个技巧能够让人在他那圈子里感觉非常特别。即使是一个废柴技巧也能引起人们足够的兴趣来。

c++中有多少阴暗角落呢?c++中有多少技巧呢?这一切的一切,c++中有多少偶然的复杂性呢?

平心而论,近年来(现代c++)发现的大多数技巧或技术(如果你愿意这么说的话)实际上是由实际需要驱动的,尤其是需要实现高度灵活而又普遍适用(generic)的类库(例如boost中的那些玩意)。而这些技巧也的确(在某种程度上)提供了对实际问题的漂亮解决方案。让我们来这么想一下,如果你处于一个两难境地,要么用那些奇技淫巧来做点很有用的东西,要么不做这样其他人也就没的用。你会如何选择呢?我知道boost的英雄们选择了前者——不管多么困难多么变态多么龌龊,把它做出来!

#waterwalk 发表于2007-09-14 14:07:55  IP: 219.131.196.*
但所有这些争论都不能改变一个事实:我们应该有一个语言能够让我们用代码清晰的表达思想。以boost.function/boost.bind/boost.tuple为例,variadic templates可以大大简化这几个库的实现(只有1/10的代码行数),同时代码也更加简洁易懂。Auto, initializer-list, rvalue-reference, template-aliasing, strong-typed enums, delegating-constructors, constexpr, alignments, inheriting-constructors,等等等等,所有这些c++0x的特性,都有一个共同目的——消除语言中多方面的偶然复杂性或语言中的尴尬之处。

正如Bjarne Stroustrup所说,很显然c++太过复杂了,很显然人们被吓坏了,并且时不时就不用c++了。但“人们需要相对复杂的语言去解决绝对复杂的问题”。我们不能通过减少语言特性而使其更加强大。复杂的特性例如模版甚至多继承也是有用的——如果你正好需要它们,你只需小心使用,这样就不会搬起石头砸自己的脚了。在所有这些c++的复杂性当中,真正阻碍了我们的是“偶然复杂性”(有人称之为“尴尬之处”),而不是语言所支持的编程范式(其实也就3个而已)。这也是我们应该拥抱c++0x的重要原因
,因为c++0x正是要消除那些长期存在的偶然复杂性,同时也使得那些奇技淫巧不再必要(很显然,目前这些技巧堆积如山,翻翻那些个c++的书籍,或者瞅瞅boost库,你就知道我在说啥了),这样我们就能够直观清晰的表达思想。
#waterwalk 发表于2007-09-14 14:10:50  IP: 219.131.196.*
结论
c++难用,更难用对。所以当你决定用它时,要小心,要时刻牢记自己所处的位置,所要达到的目的。这里有一个简单的指南:

我们需要高效率么?

如果需要,那么

我们需要抽象么(请仔细思考这一点,因为很难评估使用c++高级特性是否能够抵消误用这些机制的风险;正确的回答取决于程序员的水平有多高,遵循哪种编码标准以及编码标准执行得如何,等等)?

如果是,那么用c++吧。如果不是,那么,

我们需要用c++库来简化开发么?

如果是,那就用c++吧。但同时必须时刻牢记你在做什么——如果你的代码不需要那些奇妙抽象,那就别试图使用以免陷入其中。别只是因为你在.cpp文件中用c++编码就要用类啊、模版啊这些东西。

如果不是,那就用c,不过你又会想为啥不仅仅使用c++中属于c的那部分核心呢?还是老原因:人们很容易就陷入到语言的奇妙特性中去了,即使他们还不知道这些特性是否有用。我都记不清有多少次自己写了一大堆的类,到最后反倒要问自己“要这么些个类做什么呀?”。所以,如果你能坚持只用c++中c或c with class的那部分,让简单的事情保持简单;或者需要把c代码迁移到c++中来,那么就用c++吧,但要十分小心。另一方面,如果你既不需要抽象机制,也不需要c++库,因为事情非常简单,不需要方便的组件例如容器和字符串,或者你已认定c++能够给项目带来的好处微乎其微,不值得为之冒风险,或者干脆就没那么多人能用好c++,那么可能你还是只用c的好。

底线是:让简单的事情保持简单(但同时也请记住:简单性可以通过使用高级库来获得);必要时使用抽象(切记不可滥用;遵循好的设计方法,培养好的习惯)。
#waterwalk 发表于2007-09-14 14:11:13  IP: 219.131.196.*
---全文完---
#pongba 发表于2007-09-14 15:28:46  IP: 222.94.3.*
非常感谢waterwalk兄花费这么多时间,我整理一下另发一个帖子 :-)
#yhmhappy2006 发表于2007-09-16 16:29:45  IP: 60.12.8.*
great!
请教刘老师,c++0x中加入自动垃圾收集清理了吗?
我觉得这是c++发展的关键!愚见,不要笑话俺,^_^
#Asmodeus 发表于2007-09-17 01:43:52  IP: 221.216.148.*
Great post! Learned a lot from your blog. Keep good work going!

I'm a beginner in C++. Could you give me some examples of the "better string implementation"?

Thanx a lot.
#pongba 发表于2007-09-17 17:37:15  IP: 222.94.3.*
to asmodeus:
see "Exceptional C++ Style", Chapter 37 :)
发表评论