你应当如何学习C++(以及编程)(rev#1)
By 刘未鹏(pongba)
C++的罗浮宫(http://blog.csdn.net/pongba)
Javascript是世界上最受误解的语言,其实C++何尝不是。坊间流传的错误的C++学习方法一抓就是一大把。我自己在学习C++的过程中也走了许多弯路,浪费了不少时间。
为什么会存在这么多错误认识?原因主要有三个,一是C++语言的细节太多。二是一些著名的C++书籍总在(不管有意还是无意)暗示语言细节的重要性和有趣。三是现代C++库的开发哲学必须用到一些犄角旮旯的语言细节(但注意,是库设计,不是日常编程)。这些共同塑造了C++社群的整体心态和哲学。
单是第一条还未必能够成气候,其它语言的细节也不少(尽管比起C++起来还是小巫见大巫),就拿javascript来说,作用域规则,名字查找,closure,for/in,这些都是细节,而且其中还有违反直觉的。但许多动态语言的程序员的理念我猜大约是学到哪用到哪罢。但C++就不一样了,学C++之人有一种类似于被暗示的潜在心态,就是一定要先把语言核心基本上吃透了才能下手写出漂亮的程序。这首先就错了。这个意识形成的原因在第二点,C++书籍。市面上的C++书籍不计其数,但有一个共同的缺点,就是讲语言细节的书太多——《C++ gotchas》,《Effective C++》,《More Effective C++》,但无可厚非的是,C++是这样一门语言:要拿它满足现代编程理念的需求,尤其是C++库开发的需求,还必须得关注语言细节,乃至于在C++中利用语言细节已经成了一门学问。比如C++模板在设计之初根本没有想到模板元编程这回事,更没想到C++模板系统是图灵完备的,这也就导致了《Modern C++ Design》和《C++ Template Metaprogramming》的惊世骇俗。这些技术的出现为什么惊世骇俗,打个比方,就好比是一块大家都认为已经熟悉无比,再无秘密可言的土地上,突然某天有人挖到原来地下还蕴藏着最丰富的石油。在这之前的C++虽然也有一些细节,但也还算容易掌握,那可是C++程序员们的happy old times,因为C++的一切都一览无余,everything is figured out。然而《Modern C++ Design》的出世告诉人们,“瞧,还有多少细节你们没有掌握啊。”于是C++程序员们久违的激情被重燃起来,奋不顾身的踏入细节的沼泽中。尤其是,模板编程将C++的细节进一步挖掘到了极致——我们干嘛关心涉及类对象的隐式转换的优先级高低?看看boost::is_base_of就可以知道有多诡异了。但最大的问题还在于,对于这些细节的关注还真有它合适的理由:我们要开发现代模板库,要开发active library,就必须动用模板编程技术,要动用模板编程技术,就必须利用语言的犄角旮旯,enable_if,type_traits,甚至连早就古井无波的C宏也在乱世中重生,看看boost::preprocessor有多诡异就知道了,连C宏的图灵完备性(预编译期的)都被挖掘出来了。为什么要做这些?好玩?标榜?都不是,开发库的实际需求。但这也正是最大的悲哀了。在boost里面因实际需求而动用语言细节最终居然能神奇的完成任务的最好教材就是boost::foreach,这个小设施对语言细节的发掘达到了惊天地泣鬼神的地步,不信你先试着自己去看看它的源代码,再看看作者介绍它的文章吧。而boost::typeof也不甘其后——C++语言里面有太多被“发现”而不是被“发明”的技术。难道最初无意设置这些语言规则的家伙们都是oracles?
因为没有variadic templates,人们用宏加上缺省模板参数来实现类似效果。因为没有concepts,人们用模板加上析构函数的细节来完成类似工作。因为没有typeof,人们用模板元编程和宏加上无尽的细节来实现目标… C++开发者们的DIY精神不可谓不强。
然而,如果仅仅是因为要开发优秀的库,那么涉及这些细节都还是情有可原的,至少在C++09出现并且编译器厂商跟上之前,这些都还能说是不得已而为之。但我们广大的C++程序员呢?大众是容易被误导的,我也曾经是。以为掌握了更多的语言细节就更牛,但实际却是那些语言细节十有八九是平时编程用都用不到的。C++中众多的细节虽然在库设计者手里面有其用武之地,但普通程序员则根本无需过多关注,尤其是没有实际动机的关注。一般性的编码实践准则,以及基本的编程能力和基本功,乃至基本的程序设计理论以及算法设计。才是真正需要花时间掌握的东西。
学习最佳编码实践比学习C++更重要。看优秀的代码也比埋头用差劲的编码方式写垃圾代码要有效。直接、清晰、明了、KISS地表达意图比玩编码花招要重要…
避免去过问任何语言细节,除非必要。这个必要是指在实际编程当中遇到问题,这样就算需要过问细节,也是最省事的,懒惰者原则嘛。一个掌握了基本的编程理念并有较强学习能力的程序员在用一门陌生的语言编程时就算拿着那本语言的圣经从索引翻起也可以编出合格的程序来。十年学会编程不是指对每门语言都得十年,那一辈子才能学几门语言哪,如果按字母顺序学的话一辈子都别指望学到Ruby了;十年学习编程更不是指先把语言特性从粗到细全都吃透才敢下手编程,在实践中提高才是最重要的。
至于这种抠语言细节的哲学为何能在社群里面呈野火燎原之势,就是一个心理学的问题了。想像人们在论坛上讨论问题时,一个对语言把握很细致的人肯定能够得到更多的佩服,而由于论坛上的问题大多是小问题,所以解决实际问题的真正能力并不能得到显现,也就是说,知识型的人能够得到更多佩服,后者便成为动力和仿效的砝码。然而真正的编程能力是与语言细节没关系的,熟练运用一门语言能够帮你最佳表达你的意图,但熟练运用一门语言绝不意味着要把它的边边角角全都记住。懂得一些常识,有了编程的基本直觉,遇到一些细节错误的时候再去查书,是最节省时间的办法。
C++的书,Bjarne的圣经《The C++ Programming Language》是高屋建瓴的。《大规模C++程序设计》是挺务实的。《Accelerated C++》是最佳入门的。《C++ Templates》是仅作参考的。《C++ Template Metaprogramming》是精力过剩者可以玩一玩的,普通程序员碰都别碰的。《ISO.IEC C++ Standard 14882》不是拿来读的。Bjarne最近在做C++的教育,新书是绝对可以期待的。
P.S. 关于如何学习编程,g9的blog上有许多精彩的文章:这里,这里,这里,这里… 实际上,我建议你去把g9老大的blog翻个底朝天 :P
再P.S. 书单?我是遑于给出一个类似《C++初学者必读》这种书单的。C++的书不计其数,被公认的好书也不胜枚举。只不过有些书容易给初学者造成一种错觉,就是“学习C++就应该是这个样子的”。比如有朋友提到的《高质量C/C++编程》,这本书有价值,但不适合初学者,初学者读这样的书容易一叶障目不见泰山。实际上,正确的态度是,细节是必要的。但细节是次要的。其实学习编程我觉得应该最先学习如何用伪码表达思想呢,君不见《Introduction to Algorithm》里面的代码?《TAOCP》中的代码?哦,对了它们是自己建立的语言,但这种仅教学目的的语言的目的就是为了避免让写程序的人一开始就忘了写程序是为了完成功能,以为写程序就是和语言细节作斗争了。Bjarne说程序的正确性最重要,boost的编码标准里面也将正确性列在性能前面。
此外,一旦建立了正确的学习编程的理念,其实什么书(只要不是太垃圾的)都有些用处。都当成参考书,用的时候从目录或索引翻,基本就对了。
再再P.S. myan老大和g9老大都给出了许多精彩的见解。我不得不再加上一个P.S。具体我就不摘录了,如果你读到这里,请务必往下看他们的评论。转载者别忘了转载他们的评论:-)
许多朋友都问我同一个问题,到底要不要学习C++。其实这个问题问得很没有意义。“学C++”和“不学C++”这个二分法是没意义的,为什么?因为这个问题很表面,甚至很浮躁。重要的不是你掌握的语言,而是你掌握的能力,借用myan老大的话,“重要的是这个磨练过程,而不是结果,要的是你粗壮的腿,而不是你身上背的那袋盐巴。”。此外学习C++的意义其实真的是醉翁之意不在酒,像C/C++这种系统级语言,在学习的过程中必须要涉及到一些底层知识,如内存管理、编译连接系统、汇编语言、硬件体系结构等等等等知识(注意,这不包括过分犄角旮旯的语言枝节)。这些东西也就是所谓的内功了(其实最最重要的内功还是长期学习所磨练出来的自学能力)。对此大嘴Joel在《Joel On Software》里面提到的漏洞抽象定律阐述得就非常漂亮。
所以,答案是,让你成为高手的并不是你掌握什么语言,精通C++未必就能让你成为高手,不精通C++也未必就能让你成为低手。我想大家都不会怀疑g9老大如果要抄起C++做一个项目的话会比大多数自认熟练C++的人要做得漂亮。所以关键的不是语言这个表层的东西,而是底下的本质矛盾。当然,不是说那就什么语言都不要学了,按照一种曹操的逻辑,“天下语言,唯imperative与declarative耳”。C++是前者里面最复杂的一种,支持最广泛的编程范式。借用当初数学系入学大会上一个老师的话,“你数学都学了,还有什么不能学的呢?”。学语言是一个途径,如果你把它用来磨练自己,可以。如果你把它用来作为学习系统底层知识的钥匙,可以。如果你把它用来作为学习如何编写优秀的代码,如何组织大型的程序,如何进行抽象设计,可以。如果掉书袋,光啃细节,我认为不可以(除非你必须要用到细节,像boost库的coder们)。
然后再借用一下g9老大的《银弹和我们的职业》中的话:
银弹和我们的职业发展有什么相干?很简单:我们得把时间用于学习解决本质困难。新技术给高手带来方便。菜鸟们却不用指望被新技术拯救。沿用以前的比喻, 一流的摄影师不会因为相机的更新换代而丢掉饭碗,反而可能借助先进技术留下传世佳作。因为摄影的本质困难,还是摄影师的艺术感觉。热门技术也就等于相机。 不停追新,学习这个框架,那个软件,好比成天钻研不同相机的说明书。而热门技术后的来龙去脉,才好比摄影技术。为什么推出这个框架?它解决了什么其它框架 不能解决的问题?它在哪里适用?它在哪里不适用?它用了什么新的设计?它改进了哪些旧的设计?Why is forever. 和 朋友聊天时提到Steve McConnell的《Professional Software Development》里面引了一个调查,说软件开发技术的半衰期20年。也就是说20年后我们现在知识里一半的东西过时。相当不坏。朋友打趣道:“应 该说20年后IT界一半的技术过时,我们学的过时技术远远超过这个比例。具体到某人,很可能5年他就废了”。话虽悲观,但可见选择学习内容的重要性。学习 本质技艺(技术迟早过时,技艺却常用长新)还有一好处,就是不用看着自己心爱的技术受到挑战的时候干嚎。C/C++过时就过时了呗,只要有其它的系统编程 语言。Java倒了就倒了呗,未必我不能用.NET?Ruby昙花一现又如何。如果用得不爽,换到其它动态语言就是了。J2EE被废了又怎样?未必我们就 做不出分布系统了?这里还举了更多的例子。
一句话,只有人是真正的银弹。职业发展的目标,就是把自己变成银弹。那时候,你就不再是人,而是人弹。
最后就以我在Bjarne的众多访谈当中摘录的一些关于如何学习C++(以及编程)的看法结束吧(没空逐段翻译了,只将其中我觉得最重要的几段译了一下,当然,其它也很重要,这些段落是在Bjarne的所有采访稿中摘抄出来的,所以强烈建议都过目一下):
I suspect that people think too little about what they want to build, too little about what would make it correct, and too much about "efficiency" and following fashions of programming style. The key questions are always: "what do I want to do?" and "how do I know that I have done if?". Strategies for testing enters into my concerns from well before I write the firat line of code, and that despite my view that you have to write code very early - rather than wait until a design is complete.
译:我感觉人们过多关注了所谓“效率”以及跟随编程风格的潮流,却严重忽视了本不该被忽视的问题,如“我究竟想要构建什么样的系统”、“怎样才能使它正确”。最关键的问题永远是:“我究竟想要做什么?”和“如何才能知道我的系统是否已经完成了呢?”就拿我来说吧,我会在编写第一行代码之前就考虑测试方案,而且这还是在我关于应当早于设计完成之前就进行编码的观点的前提之下。
Obviously, C++ is very complex. Obviously, people get lost. However, most peple get lost when they get diverted into becoming language lawyers rather than getting lost when they have a clear idea of what they want to express and simply look at C++ language features to see how to express it. Once you know data absreaction, class hierarchies (object-oriented programming), and parameterization with types (generic programming) in a fairly general way, the C++ language features fall in place.
译:诚然,C++非常复杂。诚然,人们迷失其中了。然而问题是,大多数人不是因为首先对自己想要表达什么有了清晰的认识只不过在去C++语言中搜寻合适的语言特性时迷失的,相反,大多数人是在不觉成为语言律师的路上迷失在细节的丛林中的。事实是,只需对数据抽象、类体系结构(OOP)以及参数化类型(GP)有一个相当一般层面的了解,C++纷繁的语言特性也就清晰起来了。
Well, I don't think I made such a trade-off. I want elegant and efficient code. Sometimes I get it. These dichotomies (between efficiency versus correctness, efficiency versus programmer time, efficiency versus high-level, et cetera.) are bogus.
I think the real problem is that "we" (that is, we software developers) are in a permanent state of emergency, grasping at straws to get our work done. We perform many minor miracles through trial and error, excessive use of brute force, and lots and lots of testing, but--so often--it's not enough.
Software developers have become adept at the difficult art of building reasonably reliable systems out of unreliable parts. The snag is that often we do not know exactly how we did it: a system just "sort of evolved" into something minimally acceptable. Personally, I prefer to know when a system will work, and why it will.
There are more useful systems developed in languages deemed awful than in languages praised for being beautiful--many more. The purpose of a programming language is to help build good systems, where "good" can be defined in many ways. My brief definition is, correct, maintainable, and adequately fast. Aesthetics matter, but first and foremost a language must be useful; it must allow real-world programmers to express real-world ideas succinctly and affordably.
I'm sure that for every programmer that dislikes C++, there is one who likes it. However, a friend of mine went to a conference where the keynote speaker asked the audience to indicate by show of hands, one, how many people disliked C++, and two, how many people had written a C++ program. There were twice as many people in the first group than the second. Expressing dislike of something you don't know is usually known as prejudice. Also, complainers are always louder and more certain than proponents--reasonable people acknowledge flaws. I think I know more about the problems with C++ than just about anyone, but I also know how to avoid them and how to use C++'s strengths.
In any case, I don't think it is true that the programming languages are so difficult to learn. For example, every first-year university biology textbook contains more details and deeper theory than even an expert-level programming-language book. Most applications involve standards, operating systems, libraries, and tools that far exceed modern programming languages in complexity. What is difficult is the appreciation of the underlying techniques and their application to real-world problems. Obviously, most current languages have many parts that are unnecessarily complex, but the degree of those complexities compared to some ideal minimum is often exaggerated.
We need relatively complex language to deal with absolutely complex problems. I note that English is arguably the largest and most complex language in the world (measured in number of words and idioms), but also one of the most successful.
C++ provides a nice, extended case study in the evolutionary approach. C compatibility has been far harder to maintain than I or anyone else expected. Part of the reason is that C has kept evolving, partially guided by people who insist that C++ compatibility is neither necessary nor good for C. Another reason-- probably even more important--is that organizations prefer interfaces that are in the C/C++ subset so that they can support both languages with a single effort. This leads to a constant pressure on users not to use the most powerful C++ features and to myths about why they should be used "carefully," "infrequently," or "by experts only." That, combined with backwards-looking teaching of C++, has led to many failures to reap the potential benefits of C++ as a high-level language with powerful abstraction mechanisms.
The question is how deeply integrated into the application those system dependencies are. I prefer the application to be designed conceptually in isolation from the underlying system, with an explicitly defined interface to "the outer world," and then integrated through a thin layer of interface code.
Had I had a chance to name the style of programming I like best, it would have been "class-oriented programming", but then I'm not particularly good at finding snappy names. The school of thought that I belong to - rooted in Simula and related design philosophies - emphasizes the role of compile-time checking and flexible (static) type systems. Reasoning about the behavior of a program has to be rooted in the (static) structure of the source code. The focus should be on guarantees, invariant, etc. which are closely tied to that static structure. This is the only way I know to effectively deal with correctness. Testing is essential but cannot be systematic and complete without a good internal program structure - simple-minded blackbox testing of any significant system is infeasible because of the exponential explosion of states.
So, I recommend people to think in terms of class invariants, exception handling guarantees, highly structured resource management, etc. I should add that I intensely dislike debugging (as ah hoc and unsystematic) and strongly prefer reasoning about source code and systematic testing.
Pros: flexibility, generality, performance, portability, good tool support, available on more platforms than any competitor except C, access to hardware and system resources, good availability of programmers and designers. Cons: complexity, sub-optimal use caused by poor teaching and myths.
发表于 @ 2007年05月16日 14:37:00|评论(125 )|编辑
评论
《高》是一本有用的书,我也读过。但不应该用来影响初学者的编程哲学。许多人读《高》这样的书都容易形成一种感觉,就是细节非常重要。
实际上,正确的态度是,细节是必要的。但细节是次要的。
没有提到我们出的《C++ Primer》(http://www.dearbook.com.cn/book/92394)?学C++应该由此开始。
从这个角度,我想不该是 高 ,而应该是类似于 code complete这样的书才是指导如我等一般程序员的 入门好书。
也看看《高质量C++编程指南》去
最近很喜欢用python写东西,那种简洁灵动的感觉真好。
不过话又说回来,那些“必须”用c++来解决的问题,细节问题关键时候还是显得很重要,这也是c++的强项。
可是到了03年初,就已经发现这个路子有问题。程序毕竟是以用为本,而真正有用的程序,反而在编码上往往是质朴的,强在对领域知识的理解和创新上,对用户需求的把握和体现上。从那时开始,我的思想发生了一个痛苦的嬗变。在认识到自己过去所想有问题的同时,也进入了一种迷茫状态,丧失了对一切语言和技术细节的学习兴趣。什么.NET,Java,POSIX,Compiler, Web,SOA,好玩的东西就那么一小撮,大部分细节是索然无味的,甚至面目可憎。这个状态持续了将近两年,才随着对Python、Ruby的了解而逐渐过去。
现在回过头来反思,当年拼命研究那些细节,固然是进入误区,但是何尝又不是一段历练。现在C++社群的大牛们纷纷提出要改造C++教学路径,这个我当然是支持了。现在的C++学习者可以不用绕弯路,可以直接用那些高层抽象工具解决问题,不用再苦苦理解什么函数重载决议的规则,不用为内存的高效利用而发愁,对于做具体项目来说当然幸福,但是对他们的技术成长就一定是好事吗?恐怕也未必。少了一份磨难,也就少了一份成熟。
所以我觉得,多绕点弯路其实没关系,力气还是长在了自己身上。关键还是要踏踏实实下功夫搞。如果让我回答“应当如何学习C++”这个问题,我只有一句话可说,那就是:“下足功夫”。
myan老大所说的下足工夫当然是无可厚非的。做任何事都是这样,不下足工夫不可能认识到一些东西。
但真正的问题是工夫是花在刀刃上还是刀背上。是下足工夫做语言律师还是下足工夫搞实践。
时间只有一份。对于中国的学生,尤其如此。C++的细节庞杂无比,C++的书籍满天飞,光是下足功夫学习语言核心都不知道要多久。由于时间只有一份,所以就没时间去学习更重要的编程基本功、解决实际问题的能力、算法,等等。后者同样可以达到锻炼乃至是更强的锻炼。所以,光是要下足功夫其实是避开了真正的问题。
我自己也经历了myan老大的这个过程。我的看法跟myan不一样。我认为时间是宝贵的,所以工夫自然要下,但真正的问题是,往什么地方下。
g9老大提到:
这种下功夫的方式我非常认同。窃以为这才是真正pragmatic的方式,一来用实践驱动学习有干劲,而来不容易堕入为学习而学习从而迷失的地步,三来这非常锻炼人解决实际问题的能力。四来这样的学习是最“经济”,效率最高的。
个掌握了基本的编程理念并有较强学习能力的程序员在用一门陌生的语言编程时就算拿着那本语言的圣经从索引翻起也可以编出合格的程序来。十年学会编程不是指对每门语言都得十年,那一辈子才能学几门语言哪,如果按字母顺序学的话一辈子都别指望学到Ruby了;十年学习编程更不是指先把语言特性从粗到细全都吃透才敢下手编程,在实践中提高才是最重要的。
看来都是实战派人士
中国的程序员所处的环境,语言被过份强调,而其它很多一样重要的东西却被忽略了。
推荐C++的学习方法:任务驱动方法!
学习C++还是要找一本阐述“正确C++观念”的好书,然后在实践中循序渐进。目前的大学教育,由C导入C++,实际上走了很大的弯路。不传达boost::shared_ptr胜过原生指针、不传达vector
C++09在标准库和语言上都有很大的发展。如何合理的使用、配合concept机制,如何高效的使用新一代标准库,是摆在所有C++开发者和学习者面前的新问题。也是C++教学者、传播者应该立即着手准备的课题。似乎侯捷老师、荣耀老师都有一些新动向?
“避免去过问任何语言细节,除非必要。”
“熟练运用一门语言绝不意味着要把它的边边角角全都记住。懂得一些常识,有了编程的基本直觉,遇到一些细节错误的时候再去查书,是最节省时间的办法。”
-----------------------------------------------------
联系这两段话,我以为楼主的意思是说,平时不需要去了解细节。但是不知道有没有“不去知道这些细节”的意思。如果有这个意思,那就有问题了。如果平时不多看看细节,也就是说不知道有这些东西的存在,你怎么知道要查书?怎么知道能这样作?我见过一些c++程序员,就是这样的例子。
同时,楼主又说,
“一个对语言把握很细致的人肯定能够得到更多的佩服,而由于论坛上的问题大多是小问题,所以解决实际问题的真正能力并不能得到显现”
其实这个和语言是同样的,只是解决实际问题时,关注的是相关问题域的细节而已。作为程序员,作的事情就是把实际问题用c++表达出来,那么对两者的细节都需要了解。当然,这个话的前提是:自己想成为一个牛人。我想,任何人都想自己是头牛的。
那么怎样理解BS教主的话,“实际上,正确的态度是,细节是必要的。但细节是次要的。”呢?我以为,首先是因为他已经很牛了,对相关的东西已经烂熟(不是指什么都记住,而是说能一下知道哪里找到需要的东西)。现在他关心的领域已经改变了,细节也转移到相关的领域了。看看教主写的c++演化这个书,就知道在设计c++的时候,对细节是多么的关注。因为这个时候,他关注的领域是c++。
你的基本观点我当然是赞同,相信每个从细节走出来的人都会赞同。问题在于对于初学者(当然主要是学生),怎么走合适。你说:
“时间只有一份。对于中国的学生,尤其如此。”
事实上,任何工作了几年的人都能感觉到,学生阶段是最有时间的,工作了以后就没时间了。所以如果要走弯路,要琢磨一点语言细节,要做一点吃饱了撑的事情,练一点内功,最好在学生阶段走。当然,你觉得,如果在学生阶段都不走弯路,那岂不是更好?看上去当然更好,但是走弯路是不是真的可以避免,那条路是不是弯路,你指的路是不是就那么直,不那么好说的。特别是在你人生不同的阶段,你会对自己的过去有不同的看法和评价。我的观点就是,总体上讲,弯路是不可避免的,走弯路也不全是坏事,甚至在年轻的时候多走弯路,可能是太好太好的事情了。你以为的直路,说不定到头来是更大的弯路。人生的事情很难说清楚,最不用后悔的是受磨砺,最不用担心的是没机会。
至于那条“直路”,对于学生来说还挺令人向往的,可等到工作阶段,你立刻就能体会到是个什么感觉了。每天都被任务驱动着,根本不用自己费力去找“pragmatic”方式,每天都是街头喋血,连回去练练扎马步、丹田气的机会不多。到时候别说语言细节,就是一些必要的应用数学、算法理论之类的东西,也只能见缝插针学一点,囫囵吞枣,解决问题就好。实际上未鹏你是中国学生里的一个异数,你在学生阶段踏踏实实搞了一些“语言律师”的东西,因此现在有所反思,觉得自己应该早点街头肉搏,而且现在你去街头肉搏,最多已开始有点不适应,一旦适应之后,你就够厉害,因为你内功厚。但是大多数学生,他们一开始的学习方式就是你所倡导的“pragmatic”街头喋血。但是他们的结果,不是写出Notes规则引擎,不是开发出联众,而是搞了多年ASP,不知道HTTP原理;学了三年.NET,但就是理解不了异步编程模型,一碰到BeginInvoke就发怵;写了两年MFC程序,不理解Windows事件模型,一遇到问题就只能抓瞎。我这些说法都不是凭空说的,背后都有我身边的实际例子。如果你把视野放的足够大,你就会认识到,中国的学生不是太务虚,而是太务实,不是太不实用主义,而是太实用主义了。所以我觉得你的这个呼吁,对于一小部分人来说是合适的,对于绝大多数人来说是不适用的。
当然,工作当中需要了解的细节也是有的,比如做国际化的人,需要对字符编码的问题滚瓜烂熟,搞Windows向Linux移植的人,需要对Windows内部钩子的实现、Linux/X系统内部事件机制了然于心;搞WinCE开发,需要对微软ActiveSync的一些编程接口非常熟练。这些细节,或者说特定领域的知识技术,没有具体的应用背景和支撑环境,是不可能学进去的。因此现在大公司招高校毕业生,普遍比较理性,知道学生没有那个环境和条件搞pragmatic,一般都是不要求的。就看你基础打得扎实不扎实,有没有钻研精神。重要的是这个磨练过程,而不是结果,要的是你粗壮的腿,而不是你身上背的那袋盐巴。
我曾经问过一个美国大学的教授,是一项国际大学生编程大赛的主席,那些编程大赛的题目究竟对实际软件开发有什么用?他说,其实他们也知道不太有用,但是第一只有这个形式的东西搞比赛容易操作,真正有用的东西没法比赛,第二,重要的是选手参与这个比赛的过程,要想取得最好的成绩,往往要花几年时间,做几千题,几千道跟实际软件开发没太多关系的题。最后证明,在这个大赛中取得好成绩的,以后在工作中大多
最后,其实这些话是写给你的,也是写给我自己的。10年前的这个时候,正好是我已经熟练掌握了C,开始雄心勃勃地向C++主峰发起进攻的时候。今天如果能够让我年轻10岁,回到大学里重新选择,我可能不会选择深入研究C++,而是把C学透了,就去研究OS、Compiler、TCP/IP。但是当年我看不到这些,只能看到C++。我后悔吗?不太后悔。人只能在一种局限性与另一种局限性之中选择,走了那条路,今天就会后悔别的事情。如今我对IT这个产业链有所了解之后,更觉得世界之大,岂是一人一时所能逆料。所以全局最优是可望不可及的,个人所能做的,只是追求局部最优而已,然后让命运的大浪把你送上高峰或者拍入深渊。比如,你以为出国读书,一定是好?你以为被一流大公司高薪聘请,一定是妙?你以为你在学生阶段写出一个软件,搞得天下闻名,万人敬仰,就一定有好结局?真的不一定啊。但是不一定,是不是我们就可以吊儿郎当,游手好闲?当然不是。全局最优不可期盼,但局部最优一定要努力争取,要按照自己定的路线去踏踏实实的努力,取得尽可能好的成果。所以,你要想做个好的语言律师,就踏踏实实下功夫去做吧,没什么不对的。还是那句话,下足功夫,练出一副好身板,比什么都重要。如果说后悔,我从不后悔技术路线的选择,只是后悔那时候下得功夫还是不够,还是拿出太多的时间去看电视,吃烧烤了。
刘老大现在做什么工作呢?或者还在读书?
g9老大现在做什么工作呢?或者还在读书?
myan老大现在做什么工作呢?或者还在读书?
上帝造了天地人,就有了万物,其中还有C++。
然后C++就成了上帝,开始创造一切。
重要的是这个磨练过程,而不是结果,要的是你粗壮的腿,而不是你身上背的那袋盐巴。
初学者迷茫是学什么?学哪门语言?学这个语言的哪些细节?细节研究到什么程度?是能做出考试题就够了?是能做出面试题就够了?是能回答论坛上的问题就够了?怎么学?死啃书?啃哪些书?去实习?怎么找实习?找哪方面的实习?等等等等,时间往往在犹豫在松懈的时候滑过去了。
所以非常认同myan老大说的,重要的是过程,是不是坚持了,是不是专注了,是不是做到局部最优了。
细节以后慢慢在熟悉。
平时多学些库才是重要的,
像Qt/Gdal/Open...
我觉得能熟练使用一些重要的库才是资本。
像C++模板元这些东西是用来玩的。
==
http://chaishushan.googlepages.com
很想转载连接! 呵呵。
下面有点个人观点:
关于细节,还是应该适度关注。可以适度的拉伸深度和广度(原来还有这一手嘛,所以也算得上广度)。我以前是很不怎么习惯模版的,但实际上现在基本天天和模版交互。而且真正用时,经常会考虑我是改用vector还是string还是deque。
我一直觉得能力,并不等于知识;知识不能转化为能力,或多或少沦为有书呆子嫌疑。但现在发现很多时候缺乏论证的资料数据。体现出信息、内容的缺乏,也是就知识缺乏。
在大学时想办法实现复杂的算法,觉得那也是编程;逐渐就发现编程不等于软件,而我们要做的并不是编程,而是软件。—— 其实,我觉得对于算法的强调,一定程度导致了所谓国内程序员不错,但软件很糟。
………………
工作太忙,现在没时间多说,等以后有空了写篇文章。
既然这样,在C++的学习方法上,我觉得lz的方法应该算得上是局部最优的。
这么说来,二者是不矛盾的。呵呵!
我个人很喜欢往细节底层里钻,喜欢《C++ Primer》,喜欢看Lippman把深藏在水下的东西都翻出来展示给大家看,也非常的固执的认为,没有掌握OS和Win32之前,绝对不要碰VC或者BC。
有时间也很迷茫,因为学了那么久,现在也不能写个像样的东西出来。pongba老大说的细节问题反应在论坛上,myan老大说的务实问题反应在学校里,的确是这样。
学校里,没有人会在乎你懂得重载函数的解析过程,或者是说清楚指向函数指针数组的指针这些杂七杂八的东西。“什么?你用Dephi做了一个航空管理系统!”“这个在线答题系统是你用Java设计的?!牛!”通常是这么回事。一方面,企业对于项目经验的要求;另一方面,是学生自己“学以致用”的思想,两者结合,就出现了myan老大说的那种“中国的学生不是太务虚,而是太务实”的观点。是啊,学了没有用的东西,谁会去学。“学OS能写操作系统吗?”“学编译能写Complier吗?”不能,所以还不如学学如何在C++ Builder中拖放控件做个画图程序更有用。
论坛上就不同了,高手低手汇聚一堂,能写航空管理系统算啥,能写虚拟机的人都多得数不过来。当然,能说清楚类模板的名字解析的人就很少了。能开发项目,能写底层,但要是给一张大学C++试卷,能难说能不能及格。细节出于此,在网络上,大家都喜欢把语言的底层机制翻来覆去的玩耍。
我想myan老大考虑的是,工作后不像在大学里,有足够的时间能系统的学习细节和底层,所以偏重于强调大学期间修炼内功。pongba老大从C++学习来分析程序设计的学习之路,强调不要死抠细节,毕竟编程不是单纯的语言控制。两位老大都说得在理。
1 不仅仅是软件业,各个行业可能都需要不同层次的人才。我们固然不喜欢走出的都是只会if else的软件蓝领,但是个个超脱牛比也未必见得好事。不管是纵向深入,还是横向发展。我们都在遵循一个金字塔式的构成。关键是在合适的岗位要做到合格,具备胜任(或者只需要胜任)的能力。在这个基础上讨论才有意义--技术的挖掘是没有尽头的,未鹏在思考是否在细节上浪费了时间,孟岩说的是对那些没有具备基本合格功力从业者的忧虑,并无矛盾。
2 对于编程,我肤浅的以为,云风的认识应该是较具有说服力的,毕竟在一线干了这么多年。记得以前讨论过“编程的能力”,那么,我想,就像骑自行车一样,大家都会骑,但是未必都要去成为专业的自行车运动员--能骑就行,当然,爱好者越多越好。那些不会骑的,或者佯装骑行数年的,固然值得忧虑。正确的软件思维方式,正确的开发流程认识前提下,对语言的热爱只是肯德基和麦当劳对中国人的区别--随你爷高兴。
3 从学习编程的能力上来说,C++是一门需要苦行僧精神的语言。我十分推荐用python来入门,别忘了,我们编程,我们写软件,说到底也是为了自动化地做事罢了。从这个意义上说,我曾经的吃饱喝足的蠢猪leader倒也不错,.bat写得很好。
4 顺道赞一下未鹏这次挖的坑阿,大家跳啊。
--
www.cnzhangzhen.com
在我见过牛人之前,总是想多了解些“知识”,见到真正的牛人后,发现差别在于思维方式、编程的习惯和做事的技巧上。而不是技巧知道的多或少。
如果你还在学校学习,请向你的C++老师推荐《C++ Primer》第4版和《C++编程规范》这两本书。C++语言如此丰富,招数如此之多,知道哪些是更有效的也许比全面掌握更为重要。
但一个团队中如果有一个这样的语言专家存在,那么将对整个项目组来说是一个福音.
1.pongba的意思是在学习的过程中不要死抠着语言的细节不放,而应该在本质的,通用的,一般性的东西上面下功夫.
2.myan的意思是不要仅仅停留在某一技术的表面,而应该了解其本质和原理,做一些深入的探究.
其实二者的本意是一致的,都是要鼓励大家多学习本质的,通用的,一般性的东西.唯一的不同是pongba希望大家不要抠着语言细节,myan希望大家不要永远停留在表面.
一种是技术细节(比如算法细节)。
如果不重视语言细节,不能编程这是必然的。但是,可以临时查阅参考资料或是google一下。
对于技术细节(算法或是尤理论衍生出的思维模式)那可是一切的核心,是超越语言。也许工作的时候可以“copy",但是能力是不能“copy”的。试想一下,能不能进行理论研究?能不能像高手一样搞个发明?其实,中国还不断的重复知识——这几乎是弱者变成强者的有效路径。而检验我们成为强者没有的方式:便是看我们能否独立的创造。
学习一门编程语言到一定程度够用就可以了(什么程度够用只有自己最清楚),一个劲儿往下死抠也没什么意思。其实很多编程语言大同小异,学了这个又学那个真的是一件无聊的事情,太没有挑战性了。
对于pongda的说法,我认为是对的,掌握了一门语言的基本用法之后,其他细节的学习可以采用任务驱动的方式,但前提是掌握了基本用法。
很佩服myan大哥,过来人就是不一样,境界要更高一些。也许有一天,当你研究过了os,compiler,tcp/ip,会发现《计算机程序设计艺术》或者数学也许才是最有用的。个人觉得os并不是想象的那么难,因为冯.诺伊曼模型本身并不复杂。
计算机是一门科学,是需要学习的,这在本质上和学习数学、物理、化学也没什么太大区别,只是做实验相对方便一点而已,请不要天天围着实验工具这个话题讨论好吗?
计算机不仅是门科学也是门技术,甚至技术的成分多于科学,计算机的学习本质上和数学、物理、化学的学习也没什么太大区别?照你的逻辑,只要数学家、物理学家、化学家愿意,都可以成为计算机科学家,是吗?我怎么总觉得在中国有这么多奇谈怪论呢?
上学时候,本人的学校还可以,但专业和计算机毫不相干,自然也就没有同学和老师可以探讨。宿舍里唯一的一台就机器只有每天早上5:00-6:00是不打游戏的时间,这个时间就是我上机练习程序唯一的机会。
刚学的时候,也在想,程序设计学了到底是干什么的,但没人告诉我答案。后来发现了VB,为了追求快速的成就感,就用VB做各种Windows程序;至于学C语言的理由很简单,当时英语很差,VB的关键字和语句都很长,我一开始是把int分成三个字母来记的方式学的,所以看到C的语句那么简短,自然就爆发出强烈的学习欲望,然而C也并不好学,一段段痛苦的过程也让自己经常在想,为了业余爱好累成这样,真的有必要吗?
最初,完全是目标的驱动,看到什么漂亮的界面和有意思的功能,就去模仿实现,完全没有什么章法,需要什么具体的知识,再去查找就是,曾经在私活迫在眉睫的状态下,一天一夜时间初步掌握了ADO,但这种日子持续下去,觉得没有什么实质性的进步,用VB写了一些小程序之后,也发现重复劳动越来越多,C语言也学的乱七八糟,全是黑乎乎的控制台,听人说数据结构是学程序的必备,于是抓了几本书乱看一气,后来一次偶然的机会,帮学校的几个师妹师弟参加一个比赛的时候涉及到了排序和其他的一点数据结构知识,奋战了两天一夜之后,突然发现自己开窍了,于是,看起了数据结构,操作系统,离散数学之类。。。。。。。
现在回头看看以前的那些事情,觉得程序设计语言终归是实现某些目的的方式,程序语言最初设计应该就是为了方便人来自定义和扩展计算机的功能的,对一些事情的规划和设计,还有有关平台和业务与原理性的知识(比如做网络程序时的TCPIP协议)才是首要的问题,其实那个时候更多的苦闷往往不是查不到程序语言的细节,而是有关平台内部知识的匮乏和把现实转化为程序的能力。
所以,现在推荐给好多比自己更初的初学者,一般都是这样双线并行的套路:1,操作系统,汇编,计算机网络,数据结构;2,某个具体的程序语言
说的有点乱,大家理解。
这个坑挖得很大。大到了能够引出价值观争论的地步了。
而这样的价值观分歧,从更本质看,原因大概就在于计算机科学本身就是个畸形的东西,一个建立在曾经的工具之上的科学。
我还没看完,先回复了再说:
c++的潜在心态就是挖语言的特性和技巧,不断的挖,而不是去学习QT,MFC之类的界面编程.
这点我是体会最深的了!!!!!!!!!!
也难怪有同学鄙视我学习c++这么久都没弄出他用java简单地就能做出的界面程序和数据库等网络程序.
"哭"啊,俺C++里没网络没数据库等等....
但是:花大量时间去挖去思维,对后来写应用程序的帮助很大,因为很多讲语言机制的书中都有抽象出应用程序的开发,只不过没给你提供组件类和方法调用而已.
对啊,对于活在程序员上的程序员的我们来讲,更该去思考如何构建优秀应用程序.而这些并不要求非常高的c++技巧和机制.
那些机制只在第一类程序员来讲才更显得重要.:我说的是更哈.
太对了
我就只忍不住赞同下哈,没有我再需要补充的话了.
-----------------------------------
我前段时间写了个文章,说我把那些语言看透了,说具体的语言和库的学习还没有学习数学好.(我承认后面这句话偏激了)
而遭到一个打击我自信的回复:楼主C++学精通了?我推测楼主看的C++书的顺序是:(略,他说的一点不错)C++ Templates看懂了多少?设计新思维又懂了多少?Loki库理解多少?楼主记住,C++入门需要五年.
----------------------------------
老大们知道所谓的C++入门需要五年怎么来的呢?
努力学了一门东西,学会思考举一反三后,能力就高了.什么WIN32的消息循环模式,MFC的封装,QT的信号和槽,JAVA的事件监听等都容易掌握了(但,且这些都是变数),也正如文章所说:具体这些中的细节我的确很多不知道,我也没多去钻研(但真正开发中就可得一定要弄懂哈);而是把时间花再C++中了.即便现在才知道C++/CLI(类比大哥所说的局部最优),但我想不会太难了.
我不后悔钻到语言中去.唯一遗憾的是:***,没能考入数学专业,无时无刻不存在心中的梦啊,我现在大字都在想
---------------------------------------------
我都不好意思了,回复这么多,哎,实在是忍不住啊.HOHO
同感.
"C++ Builder中拖放控件做个画图程序更有用"<-笑!
to:longtrue
的确,我也几头抓过
没办法啊,C++学的再好,公司还是先问你:精通VC6.0么?等等.........有的公司总想招聘的人当天下午就能干事.
-----------------------------------------------
恭喜
这里快成聊天室了.
呵呵,只要数学家,物理学家(撇开化学,我讨厌它)愿意,就肯定能成为计算机科学家.
我们老师总提示我们:你们出去以后不要自以为是,不要觉得能写程序,架构软件就了不起.
(我只是就事论事,不是抬高谁贬低谁,正所谓社会分工不同)
照你说的,干嘛把化学家排除?难道化学家就比数学家和物理学家智商低啊?行业不同不具有可比性,就跟体育运动一样,如果跨栏能跑过刘翔的不多,但论跑100米,比刘翔跑得快的多的是.争论这些没啥意义,如果自己真的是喜欢计算机这个行当,那就扎扎实实在这个行当做点事情,我们国家现在即没在计算机理论上也没在实践上做出什么象样的东西,成天讨论这些所谓的方法,等有一大批人能把CPU,OS,compiler,dbms玩弄于股掌,再来讨论这些方法,哪个时候的体会才有说服力,当下该做的是把没搞清楚的搞清楚.别用着D版,清谈方法.
不过BJ不喜欢的马克思的原因是马克思只考虑大众,不考虑到个人了:)
为什么不能把foreach这些特性当作语言的基本功能,
而非要去寻求它的具体实现机制呢???
象在Qt中,foreach就是作为一个扩充功能出现的,
至于怎么实现鬼才管!
QLinkedList
Movie movie;
...
foreach (movie, list)
{
if (movie.title() == "Citizen Kane") {
cout << "Found Citizen Kane" << endl;
break;
}
}
还有,像虚函数这些技术在java中大家就当它本来就是这样,
但是到了C++中就非得搞出什么虚函数指针列表出来!!
语言本来就是工具,你用它就是了,没有必要知道怎么才能
实现这种功能——你又不是做C++编译器的!!
我觉得《高质量C++/c编程指南》并没有强调语言的细节,只是强调编程风格的统一,和容易犯的指针,内存,if 等错误。
当然 任务驱动的学习也不错,呵
不过还是更偏向于同意孟岩老师的观点。:P
至于论坛里的情况,我个人觉得没有必要去做过多的分析和争论了。因为这个跟C++语言本身关系并不是很大,问题没有那么复杂的,相反,非常简单,就是因为“并非所有的问题都适合在论坛里讨论”。论坛里可能还是灌水更适合一些,能讨论语言细节的好帖子已属难得了。而那些乐衷于解决“实际问题”,动辄把自己项目中的成百上千行代码帖到论坛里来让别人找问题的帖子,我是从来不看的。绝对不是说这种问题不好,而是说它不适合在论坛这种环境中讨论。不知道别人怎样的,我个人是只有工作累了的时候才会泡泡论坛。:P
你说的没错,这就是为什么我在文章开头说我自己也曾走了不少弯路,浪费了不少时间的原因。也是写这篇文章的初衷。
不过后来看大伙的意见,倾向于认为即便走弯路,也是很大的锻炼。药的是好身板(在走弯路中得到),不是那点技术储备。
不管怎样,作自己的判断,认识自己并走一条最适合自己的路。这是最重要的。
刘老大最后说的 "认识自己并走一条最适合自己的路。这是最重要的" 我很支持.
顶!
我看了c++ template 确实被细节给淹没了
看不下去了
好帖大家顶一顶
看看你们说说这些东西,就知道你们的水平了.还这么多人支持楼主,无知呀!唉,所以中国出不了大师.
要有自己的方法!
“你数学都学了,还有什么不能学的”这句话完全错误。
数学的思维跟面向对象编程的思维是不同。数学好不仅对OO编程无帮助,反而构成思维的障碍。数学是一种过程式思维,而OO编程则是对象式的思维。
在很多公司里都能发现:数学好的编不好程序,编程高手数学很烂
席地而坐
想来各位大侠都是此中高手,虽然各自“武功”不同,但肯定都是无数次经验教训的总结,对我们这些刚入道的后辈都有很大帮助。
看了这么多,越看越汗颜:高手都说学语言要下苦工夫,可咱这些年在学校电脑接触的可不少,用来学习的可不多。眼瞅这就毕业的人了,还是一窍不通!!
前一阵子受一位老师的“感化”下定决心血拼VC,今天搞了半天MFC头晕脑涨上网闲逛看到了这篇帖子,很有感觉,顺便借此机会请教请教。前面那位仁兄说OS和Win32没学成就不要碰VC,我正好就是这种情况,是不是要“从头收拾旧山河”?
新手泣留,望回!!!
感觉你的问题主要是基础不牢靠。
语言是上层建筑,如果下层根基打不好就来学语言,终究还是不稳当的。汇编、数据结构与算法、计算机系体结构这些大一的基础课程,不知道学了多少呢。如果没有的话还是先把《深入理解计算机系统》之类的书拿来翻一翻为好。
也是,语言这东西的确,只有你站到了一定的高度才能看的更深吧。
可能就是因为我底层的知识不牢靠,感觉学什么的模模糊糊,似懂非懂。
但就是一个VC真的要打那么多的基础吗,不是有人也说,咱不是编译器,干吗要知道工作原理呐,只要会用不就行了吗?
嘿嘿,可能咱有点急功近利了,我其实也不算是计算机专业的,所以有些东西搞的也不太明白。
不管怎么样,还是谢谢大哥对小弟的指点。
虽然现在快大四了,但我还是很努力地补课
我觉得学习是要讲究方法,但不能只站在一定高度去学,就像你在游泳池里游得很轻松,在游泳池里游泳有好几年的经验,总结了很多方法,但你还是要去大湖大海去试一试的
没有“最快”的。在学习上,走捷径的想法本来就是错误的。
可以看看《Introduction to Algorithm》,eMule上也有作者的教学视频下,很精彩。
如果还没有准备好看TAOCP的话。
STL的数据结构实现是 实现技术,并非理论。建议先把理论掌握牢靠再去看实现。
无论如何,浮躁都是大忌。
我本人是从计算机底层进入学习的,对计算机的认识,我想还算可以。但算法就比较弱,而FP乃至更基本的计算理论如图灵机等等,几乎算是文盲。刘老师的blog上每篇都有大堆我看不懂的东西就是明证。大学期间的数学学得比较荒废——另外,学校开课我肯定是有问题的,离散就那么一小本儿还只学了一半,感觉学到的跟计算机相差巨远,连联系都无从寻找。能否请各位示下,像我这种情况的,应该如何提高自己?
PS.BS一下CSDN blog的验证码……第十三次发送。
我怎么没早发现此地?
《更好的C++——给C++使用者的D语言简介》
http://oldrev.javaeye.com/blog/123677
怎么就没有人介绍给我呢!!!!!
孟岩说的是态度问题,LZ说的是方向问题。
2。找个适合自己的学习方法。
3。不注重细节的人,必定失败。过分注重的细节的人,难成大事。
4。实践建立在获得了一定的理论知识之后,否则就是空中楼阁。
5。实践与学习应该构成闭环控制系统。
外国技术文章专区现在开张 - 目的是提供一个统一的地方, 给各编程爱好者阅读欣赏外国先进的编程技术
http://english.kingofcoder.com
回想当时学C++时的心态,真的是这样。作者真是有心,佩服。
还是那句话:“思考方式决定一切”。
就C++而言,至少,你要学会《The C++ programming language》