Learn why and how to learn C++ (and programming)

My blog has long focused on the technology and details of C++, often making readers and applicants feel embarrassed. However, in May, an article titled "How should you learn C++" reached over 30,000 reads, becoming the most-read article on the blog—far surpassing the second-highest. Why did this single article provoke so many responses? It must be that the domestic C++ community has been suppressed by C++ for too long, or more accurately, by its education. In fact, whether in major domestic forums, international C++ communities like comp.lang.c++.moderated, or even on Douban groups, those interested can see that attention to the details of the C++ language has never stopped. Similarly, complaints about these details have never ceased. For example, James Kanze, a technical expert on comp.lang.c++.moderated, mentioned that after ten years of working with C++, he still needs to refer to the C++ standard from time to time. This explains why Eric Raymond once said, "C++ is anti-compact," as noted in "The Art of Unix Programming." There are too many details in C++, and even if you've seen them, you can't remember them all. More importantly, even if you do remember, it doesn't make you a better programmer.

Many people attribute too much detail (or call it "too many dark corners") to the essence of C++, believing that all problems stem from this. Because of this, around September, Linus stated on a mailing list, "C++ is a thought-provoking language; just to keep programmers away from C++, I also use C." This short statement caused a big reaction in China. Initially, Liu Jiang commented on Linus's words, followed by Yunfeng and Meng Yan expressing their opinions. I also wrote an article called "Why C++" (later published, and Bjarne made a friendly comment on it).

However, after this sudden flood of reactions, I believe the changes may not be significant. Most of the original opponents can find reasons to oppose, while the original supporters can find reasons to agree. The rest remain neutral, with both sides having valid points but still unclear. Getting rid of self-serving bias is the premise of rational thinking.

An interesting and true story from "Decision and Judgment" illustrates this: In 1980, the US Air Combat Command computer suddenly sounded an alarm—a nuclear bomb from the Soviet Union was heading toward the United States. The commander immediately dispatched troops and prepared for a nuclear war. After three minutes, engineers found a small component had malfunctioned. However, the public's reaction was fascinating: those who supported nuclear weapons now felt safer ("the facts proved such failures are completely manageable"), while others felt less secure ("such false signals might cause the Soviet Union to overreact and trigger a real nuclear war"). A similar situation occurred after the Three Mile Island nuclear leak. Opponents believed ("this shows management can't manage nuclear energy safely"), while supporters believed ("this shows the danger isn't as serious as it might be, and it's overcomeable"). Social psychology calls this phenomenon "self-serving bias." Unfortunately, "the more the truth is clarified," it only applies to rational thinkers.

Why is this so? The real reason behind the rampant "language disputes" in the programmer community isn't the quality of the language, but the observer's perspective. In the observer's eyes, the language isn't a tool, but a skill they've spent more than N years (especially C++) cultivating. Denying such skills is equivalent to denying the observer themselves. Psychologically speaking, the language isn't a tool (although there has always been such an appeal), but a belief. Such beliefs are stronger in languages that take longer to master. Interestingly, almost all "hot" communities exhibit this phenomenon: Java, Python, Ruby... not so much. Even though these languages aren't complex, programmers still invest a lot of effort learning various frameworks and libraries. Thus, the beliefs of these language communities are not necessarily stronger than the C++ community.

However, once we understand why we think of language as a belief, it helps us get rid of the "self-serving bias" when looking at language issues and view problems objectively. "When you see evidence supporting an opinion, try to think about what evidence does not support it."

So why should we get rid of self-serving bias? To become a better programmer (no one wants to use an inefficient or inappropriate language due to prejudice). To save lives (as prejudice can lead to deeper and deeper mistakes, wasting time). So, if you can reasonably think about the issues we're going to discuss, avoid self-serving bias (even if you don't spend time on C++), then we can start discussing the real problem.

Now, almost every C++ learner knows that the core issue of C++ is its complexity; even outside the C++ community, it's a fact. The masses' eyes are sharp, not to mention the obviousness of this fact.

But I've read countless articles on C++ complexity, including the "spit-stars" arguing about it (including two C++ summaries I wrote earlier). I always feel it's not analyzed properly, like a blind person. As a reader of "Why C++" criticized, I didn't write in the article what "non-essential complexity" in C++ is. Of course, I know it myself, and those exposed to C++ for a while can generally know, but novices and even non-novices don't have a clear understanding of what I call "non-essential complexity." "Why C++" breaks away from the original intent—for all C++ users and learners.

For the same reason, after writing "How Should You Learn C++," when Mr. Meng Yan invited me to write a series of articles for "Programmer" to introduce my attitude and understanding change in the process of contacting C++, although I was very happy to agree, three months have passed. Why? Because I feel the real essential problem hasn't been clearly touched; so I haven't used the pen until now, not to say a lot of nonsense, besides being able to read as a novel, really consider whether to learn or even use C++. People may not have any practical use.

However, such a thought has always been in the subconscious. I talked to Bjarne a while ago and discussed some of the ideas about the complexity of C++. I summarized the source of C++ complexity in the email, and I feel much clearer. The purpose of this article is to convey a concrete and clear understanding of the complexity of C++. With this understanding as a support, we can deduce the best (practical) approach to learning C++.

Why study (and use) C++?

Obviously, if you can't find a reason to learn C++, talking about "correct learning methods" is equivalent to nonsense.

First, repeat Bjarne's words: "Our system is extremely complex. To avoid the complexity of C++ and simply not use C++ (Linus's approach), it is tantamount to ruining." In all areas where C and C++ are available, C++ is a better language than C. When I say "better," I mean C++ has a more secure type check than C, a better abstraction mechanism, and a better library. Of course, there are exceptions to everything. If your project is 1) not large. 2) doesn't use abstract mechanisms in coding. Even ADT (abstract data types, like std::complex, which doesn't contain polymorphism and inheritance) isn't used. RAII isn't used, and exceptions aren't used. 3) you don't need even the base library (like smart pointers that simplify resource management, smart containers). Then maybe you have no problem with C; so if your situation is so, don't argue with me because I can't refute you. The areas we are talking about here are roughly those places that Bjarne listed in the "C++ Application List."

The bottom line is: If you remove the unnecessary complexity in C++, leave those essential, important language features, simplify the language model, and eliminate historical burdens. Even C++ opponents may find it hard to find a reason to say "I still don't need C++." In my opinion, there is only one reason for a person who is rationally opposed to using C++ in practice: the confusion caused by the complexity of C++ is even more than the abstraction mechanism and library of C++ (in his specific project) benefit.

It is worth noting that there is a need to avoid a trap here, that is, once people have identified "C++ is not good," then the reason will "grow their own feet," that is, even if we take the complexity of C++, they may also insist on or not C++, and find a bunch of reasons for it. I assume that you are not such a person. However, perhaps most likely he would say: "The problem is that C++ we use today is not so (simple), your assumptions are not true." Yes, my assumptions are not true. But while we can't eliminate complexity, we can actually avoid complexity and avoid growth. This is also the main point of this article, let me elaborate later.

Of course, you may still say it until now. I still don't need C++ because I can use D; or if you don't need C++ for the project you're doing, you might say that I use Python. First of all, if your project can be done in Java/Python or even Ruby, then C++ is a bitter to eat. Because the language that can represent your project is not very efficient in terms of efficiency, what is the value of a language that does not have much benefit in efficiency and is more complex in complexity? Second, if your project efficiency is important, you might say that you can use D. However, the reality is that D is used very little in industry, especially in China, and there is almost none. C++ has a large number of existing code. Companies that have used C++ to do their products are almost impossible to rewrite code in other languages for a long time. As Joel said, he decided to rewrite one. Non-trivial code base == suicide. Therefore, we must at least pay attention to the following two obvious facts:

Fact 1: C++ still has a stable core market in industry.

This fact probably does not need to be elaborated. The core technology of many large companies is still supported by C++ (see the C++ application list on the Bjarne homepage). The so-called facts are not necessarily the conditions that everyone is most willing to admit, but they have to admit. C++ has accumulated a huge code base, which cannot be overturned overnight. D is indeed better than C++ from a linguistic point of view, but the most important thing is that it has not yet penetrated into industry (perhaps the root cause is that there is no money to support it, but this is not the focus of our discussion). And C, according to Bjarne himself, his observation is that the trend in the mainstream industry has always been "from C to C++", not the other way around, at least in Europe and America. In China, we can get a similar information through the recruitment situation on CSDN.

Fact 2: C++ programmers often enjoy competitive pay.

Yes, this is not a technical article that does not eat human fireworks. The logic on which this fact is based is simple: things are rare. When Andrei Alexandrescu came to China's SD2.0 conference this time, he also said in an interview: "The most profitable software (such as MS Office) is written in C++." Meng Yan also mentioned this fact on the blog. I think he is the technical editor of CSDN. The industry observation is definitely clearer than me. So I don't have much nonsense here.

Of course, the above logic does not mean that you are going to learn C++, everything depends on your interest. So if you are not in the field of application where C++ is, then this article is not written for you.

"The complexity of C++ is the root cause" - a flawed reasoning

Once we know that C++ is in need (learning and mastering) in some areas, we can discuss the core issue of "How to learn and master C++ correctly."

In fact, Bjarne has been promoting this issue for ten years. As early as 1999, Bjarne wrote "Learning C++ as A New Language" and mentioned in several technical interviews (here, here, here and here) how to correctly treat and use the various types supported in C++. The problem of abstract mechanisms. Andrew Koenig also wrote a modern C++ tutorial called "Accelerated C++" (which will be mentioned later in this book). However, has the situation of the C++ community improved over the years? As far as I know, even if there is improvement, it is very small. Learners are still blindly drilling the language details, only to see the trees are not seen in the forest; the Internet is still filled with a variety of "technical" articles and unreliable "XX recommendations for learning C++"; some industry experts with identity are still One book after another, the language of the language, and the writing of some of the common programmers' eight-life skills and the corners that can't be touched. The company that really uses C++ in the industry always asks some corners during the interview. The details of the problem, not the basic literacy of programming (no, mastering all the language details can not make you a qualified programmer). The interview idea is wrong. It is estimated that the reasoning behind it should be "If this guy doesn't know the details, then he is not familiar with the language. If he knows, then he may not be a good programmer. , but we can still further test the latter question. The problem with this concept is that the language is familiar to a certain extent (what degree will be specifically suggested later), it can be well programmed (the rest is only to look up Documentation); and many companies go too far when testing "familiarity with the language" (for example, asking the temporary object lifetime and destructor order is of course understandable, but ask how to avoid a class being copied or how to avoid it Is it built on the heap?); Of course, some language knowledge must be mastered in advance, and what will be mentioned later. When interviewing, you can't ask the language details. The key is "what to ask."

so:

Fact 3: The entire ecosystem of C++ has not improved much in the philosophy of learning C++ over the years.

why? Is it because the learning method introduced by Bjarne is technically not mentioned? Is Andrew Koenig's writing not good enough? No one can believe it. Because in fact, the reason here is not technical, but non-technical.

It is a well-known fact that, at the most basic level, the most serious problem with C++ is that it takes too much time for learners in the language learning phase. Turn over your C++ bookshelf or e-book directory, and most C++ "classics" are speaking languages. In our usual sense, to "get in" C++, it takes two or three years to spend the language. To be "proficient in" C++, it takes ten years and eight years to do it. (This is not the same thing as Peter Norvig's "ten years of learning programming". People say programming skills in general sense, not to be a language lawyer.)

Then why do I say that "the complexity of C++ is the root cause" is a flawed reasoning? Because, to let people spend a lot of time learning the complexities of language before using a language to do things, in addition to the fact of the complexity of the language itself, there is an important fact, that is, the learner's Attitude and (more important) methods. What are the attitudes and methods of most C++ learners? ——Before you actually use C++, read a linguistic book (the daily programming is not necessarily used for eight lifetimes). And why is there such a learning attitude? This is the question that really needs to be explained. In fact, there are two reasons:

Fact 4: The vast majority of C++ books on the market (including many that are widely known as “must read classics”) are actually negative textbooks.

In other words, if you pick up any C++ books (including many that are widely known as "must read classics"), then there is a great possibility that the content of this book is not what you should learn, but that you are not Should learn. There are two reasons why I say this because I was a victim. Second, and more substantial reasons, these so-called must-read classics are full of traps in C++ and various workarounds for C++ flaws (good to call Idioms or techniques); Because there are so many pitfalls and flaws in C++, a "long tail" is drawn; such books exist in all languages ("C Defects and Traps", "Effective Java", "Effective C#", etc. Etc.) However, in C++ this tail is particularly long, resulting in countless such books. Third, the defects and traps listed in these books do not distinguish the common level. For a programmer, you should want to see the order from "the most common problem to the least common problem". However, these books are all mixed together, or the content is introduced according to the technical classification of "resource management, class design, generics", which is not helpful at all. (If I see the content of a chapter, I certainly know what it says. Is it a class design or resource management, and is it nonsense?) that makes it impossible for a learner to distinguish and spend the most important time on the most common problems.

The most important thing is that the contents of these books have nothing to do with being a good programmer. They can only tell you at most - hey, be careful to fall into this trap. Or tell you - hey, you know that when you (the eight lifetimes don't necessarily meet) meet this need, can you solve this problem with this technique? After reading one book after another, in addition to the "forbidden", "alert" and "bulb" symbols in your head, the true programming quality is not growing. Or there is such a book, eager to explain the mechanism behind language implementation, but what is the nature of language features? It is used to abstract in the actual coding (speaking well, "design"), not to tell you how this feature is supported. For example, I have seen the following scenario: The interviewer asks: "Do you know virtual functions?" The answer is a bunch of explanations about the virtual function table mechanism. The interviewer asked again: "What are the benefits of the virtual function?" Why do you want virtual functions? The answer is: "Well... ah... that is... polymorphism" (at this time, I feel that the answer is not deep enough). Ask again: "What is the polymorphism?" Dumbless.

Fact 5: Even remembering all the details of a language doesn't make you a qualified programmer.

Fact 6: Understanding language implementation has its practical meaning (the hacking method in extreme situations and the rapid positioning of problems when there are underlying bugs), but if you understand the language mechanism in order to understand the language mechanism, it is out of the original meaning of learning the language.

This is often the case in C++: knowing the underlying mechanisms of language implementation, but not knowing where the meaning of the language features themselves is. The cart before the horse is upside down. why? The book is harmful. Second, all the scenes introduced in this kind of book add up to only those 20% (the 28th rule), or even 20% of the scenes (what books are, will be introduced later, I will not directly list the title, hit The face is too big, but I will list the book I think is essential). That's why I said "I don't need to use it for eight lifetimes."

Fact 7: 80% of C++ books (including some "classic") involve only 20% (or less) of the scene.

You might say, aren't these books worth watching?

My answer is yes. Not worth seeing at all. - But it's worth putting it aside as a reference when necessary (remember to flip from the index or directory, just look at the strictly necessary parts), if you are a serious programmer. Because whether you admit it or not, the power of Murphy's Law cannot be ignored - if there is a trap that you may encounter, you will always encounter it. Similarly, the cleverness of C++ is not unfounded, and sometimes it will be needed. But you don't need to put all the details and techniques of C++ in your mind before you can program it, namely:

Recommendation 1: C++ books that are discerningly read (including those widely known as "classics").

If a piece of content introduced in the book is not basically used in daily programming (belonging to 20% of the scene), then perhaps the best thing to do is to take a very general look and make an impression instead of following this line. Let's go deeper. What books should be read at the beginning of the course will be mentioned later.

In fact, in addition to language-independent programming (which you will read later), for C++, a specific language, to start programming with it, you only need to know some basic but important language knowledge (required) Read which books will be mentioned later) and the fact that there are many flaws and pitfalls in C++, and -

Recommendation 2: Develop the habit of accessing materials and documents at any time.

"Checking documents" can be said to be the most important ability (yes, ability) of a programmer; it is so important that there is a special abbreviation in English - RTFM. Why this ability is so important, the reason is simple: the knowledge of programming is too much. Not only is the amount of knowledge huge, but the details of knowledge are simply unparalleled in any discipline (just look for a framework library to look at its API documentation). Therefore, it is not only unrealistic to put such a huge amount of information in the mind, but it is also self-defeating. What you need is "meta-capacity", which is the ability to check documents - starting with the problems you are having, doing the right and reasonable analysis, predicting where the solution to the problem might be, finding information about the latter, reading Understand and apply.

Again, the same is true in C++. If you have this attitude from the very beginning of learning C++, then even if you are asked about a language detail when you are interviewing, you can confidently say that you don’t know the details. However, when you encounter the corresponding problem in the actual coding, you will definitely find the appropriate reference materials and solve the problem quickly (solving the problem is the ultimate goal). Of course, the bigger possibility is that you have already touched the 80% of the most common traps and tricks in the usual coding. Because you are using a practical and guiding way of learning, you need to learn. The traps and tricks are almost certainly in the common scene. It is more efficient to use a C++ "classic" to catch a C++ "fine study" method, because you have no practical experience, because you have no practical experience. It is likely that each of these techniques, each trap, will have the same probability of attack.

Why are C++ books on the market passionate about the details and techniques?

You opened a beer bottle with a tool that was used to open a beer bottle. Not only did you have a sense of accomplishment, but no one would think you were a cow. However, if you invent a way to open a beer bottle with two chopsticks, or if you just have a good tooth to open the bottle, it may be quite different. People will think that you are very good and powerful.

Fact 8: Everyone likes to dance with their ankles.

That is to say, if you use a tool that is natural for a purpose to do what he should do, no one will applaud, and you will not feel great. But if you combine new features with two tools that are not themselves for a certain purpose, you are an "innovator" (although perhaps there is a ready-made tool available).

And C++ is the soil of these "innovations", yes, I am talking about endless workarounds and idioms. But the problem is that these "innovations" are not innovation at all. What you must realize is that they are nothing more than a replacement solution that can't be tossed without a first-class solution. Yes, they can be called innovation to some extent, and even researching viable solutions is a very interesting thing in itself, but –

Fact 9: I know they are interesting, but in reality they are just patching solutions.

Yes, don't let go of these "innovation" schemes. The reason why you find it interesting is that when you are familiar with C++ to a certain extent, everything in C++, including defects, becomes a "established fact" for you, a background, a thing that you are used for (people are very Strongly adaptable). Therefore, when you find that there is a new possibility in this accustomed environment, you will certainly be happy. (For example, when I read Modern C++ Design, I once read from early to late, and didn’t have lunch. Eat), but actually? Other languages may have been supported by first-class, and other languages may not need this idiom at all, because they do not have these defects. In addition, from a practical point of view, more importantly, these "solutions" may not be used by your usual programming.

No, of course I am not saying that these patches are not important. As mentioned earlier, the cumbersome techniques in C++ are not unfounded, and there are always practical problems behind them. But the problem is that for our daily programming, these "real problems" are simply not able to beat eight. It is not necessary to charge 80% of the first time to put things that are used 20% of the time in your head. When you use it, you can check the documents or books.

Seeing this, another reason to shape the specific philosophy of mind in C++ must be known to you. In fact, this reason is really fundamental. One of the reasons mentioned earlier is made by the C++ book market (education), but why do people like to write these books? Further, why do people like to read these books? (I admit, I have read it with gusto.) The answer is simple: psychological. Everyone likes to dance with ankles (fact 8). Recognizing this is not to promote it, but only when we realize why we are going to delve into a bunch of patching solutions, we can really get rid of their attraction.

All in all, the complexity of C++ is only a necessary condition, not the root cause of the problem. The crux of the matter lies in the human mind. Everyone likes to dance with their ankles and thinks it is "innovation." Being aware of this can help us avoid taking unnecessary time with a wide variety of language details and techniques.

However, the complexity of C++ is always an unavoidable reality. There are a lot of pitfalls and pitfalls in C++, which leads to an amazing number of idioms and workarounds. Inadequate, pre-learning is a very bad practice. It is not only inefficient, but it is not necessary at all. It is a waste of life. Einstein once said, "I just want to know the design concept of 'he' (the universe), the others are the details." However, as other readers have pointed out, if there is no concept in advance of these details in C++, then if you encounter it in the actual code, you will become a headless fly, and you may not know where to go to RTFM. That's why so many C++ interviews take the trouble to ask some representative language details.

It’s not good to put the details in the head, but it’s not a good idea to know nothing about the details. So for C++ programmers, what kind of attitude and learning method should be used to deal with the complexity of C++? In fact, the answer is very simple. First of all, there are some important and necessary language details & features that need to be mastered. Then we only need to know where there are complexities (traps, defects) in C++, then when problems are encountered. Naturally, I know where to find the answer. Specific recommendations are given later.

C++ complexity classification

Originally, this section is intended to be a C++ complexity index. However, the complexity of C++ is too much. Secondly, there are already many materials on the Internet (for example, Bjarne Stroustrup's own C++ Technical FAQ is a good document). In most C++ books on the market, language details are kept incessant; therefore, we are not lacking in information, but lack a way to index such information, and a modular way of thinking to control these complexities.

For the above reasons, the complexity of C++ is not listed in detail here, but a classification standard is provided.

There are two classification methods for the complexity of C++. One is divided into non-essential complexity and essential complexity; non-essential complexity is divided into defects and traps. Another classification method is to classify by scene: the complexity under the library development scenario and the complexity of daily coding. From the perspective of practitioners engaged in everyday coding, the latter classification allows us to quickly grasp the complexity of 80% of the scene.

The twenty-eighth rule

The following is an explanation of this taxonomy by listing some common examples:

Complexity in 80% scenarios:

1. Resource management (the main source of C++ daily complexity): deep copy & shallow copy; four special member functions of the class; use STL; RAII idiom; smart pointer and so on.

2. Object lifetime: local & global object lifetime; temporary object destruction; object construction & destruction order, and so on.

3. Polymorphism

4. Overload resolution

5. Exceptions (unless you don't use exceptions): the stack-unwinding process; when an exception is thrown; at what abstract level an exception is thrown, and so on.

6. undefined&unspecified&implementation defines the difference between the three behaviors: i++ + ++i is undefined behavior (that is, "problem, bad behavior, theoretically anything can happen"); the order of evaluation of the parameters is Unspecified (unspecified - "you can't rely on a particular order, but its behavior is well defined"); when a double is converted to a float, if the value of the double variable cannot be accurately expressed in a float, then The choice of the next close discrete value or the last close discrete value is implementation defined (that is, "you can find the description in the implementation vendor's compiler documentation"). These issues can affect your ability to write portable code.

(Note: The above is just an incomplete list to demonstrate the meaning of this taxonomy - in fact, if we only consider the "complexity in 80% of the scenes", the burden of memory and learning will be greatly reduced.)

Complexity in 20% scenarios:

Object memory layout

2. Template: partial specialization; non-type template parameters; template parameter derivation rules; instantiation; two-stage name lookup; metaprogramming and so on.

3. Name Search & Binding Rules

4. Various defects and defect-derived workarounds (called "techniques" in C++): does not support concepts (boost.concept_check library); type-transparent typedefs (true-typedef idioms); weakly typed enumerations (Strong enumeration idiom); implicit bool conversion (safe-bool idiom); custom type does not support initialization list (boost.assign library); weak metaprogramming support (type-traits idiom; tag-dispatch idiom) ; boost.enable_if library; boost.static_assert library); right-valued defects (loki.mojo library); does not support a variable number of template parameter lists (type-list idioms); does not support native alignment specification.

(Note: The above is just an incomplete list. You will find that these details or techniques are rarely used in everyday programming, especially workarounds derived from various language defects, which constitute a huge long tail, whether in C++ or not. The books still account for a large proportion of the literature, the authors call them technology, but in fact most of these "technologies" are only needed in library development.)

Non-essential complexity & essential complexity

In addition, it is helpful to consider another classification, which is divided into non-essential complexity and essential complexity.

Non-essential complexity (incomplete list)

1. Defects (referring to problems that can be overcome, but the solution is awkward; C++'s book refers to workarounds that overcome defects as techniques, which I find very misleading): The examples have been listed in the previous section.

2. Trap (refers to an insurmountable problem, can only be carefully bypassed; if you fall into it, it means that you do not know this trap, then there is a great possibility that you do not know where to solve this problem): Generally speaking As a qualified programmer (whether or not a C++ programmer), the language trap in 80% of the scenes needs to be remembered. For example, deep copy & shallow copy; base class destructor should be virtual; default generated class member function; evaluation order & sequence point; class member initialization order & declaration order; resulting in non-portable code implementation related issues.

Essential complexity (not complete list)

Memory management

2. Object lifetime

3. Overload resolution

4. Name lookup

5. Template parameter derivation rules

6. Abnormal

7. OO(动态)和GP(静态)两种范式的应用场景和交互

总之,这一节的目的是要告诉你从一个较高的层次去把握C++中的复杂性。其中最重要的一个指导思想就是在学习的过程中注意你正学习的技术或细节到底是80%场景下的还是20%场景下的(一般来说,读完两本书——后面会提到——之后你就能够很容易的对此进行判断了),如果是20%场景下的(有大量这类复杂性,其中尤数各种各样的workarounds为巨),那么也许最好的做法是只记住一个大概,不去作任何深究。此外,一般来说,不管使用哪门语言,认识语言陷阱对于编程来说都是一个必要的条件,语言陷阱的特点是如果你掉进去了,那么很大可能意味着你本来就不知道这有个陷阱,后者很大可能意味着你不知道如何解决。

学习C++:实践者的方法

在上面写了那么多之后,如何学习C++这个问题的答案其实已经很明显了。我们所欠缺的是一个书单。

第一本

如果你是一个C++程序员,那么很大的可能性你会需要用到底层知识(硬件平台架构、缓存、指令流水线、硬件优化、内存、整数&浮点数运算等);这是因为两个主要原因:一,了解底层知识有助于写出高效的代码。二,C++这样的接近硬件的语言为了降低语言抽象的效率惩罚,在语言设计上作了很多折衷,比如内建的有限精度整型和浮点型,比如指针。这就意味着,用这类语言编程容易掉进Joel所谓的“抽象漏洞”,需要你在语言提供的抽象层面之下去思考并解决遇到的问题,此时的底层知识便能帮上大忙。因此,一本从程序员(而不是电子工程师)的角度去介绍底层知识的书会非常有帮助——这就是推荐《Computer Systems:A Programmers Perspective》(以下简称CSAPP)(中译本《深入理解计算机系统》)的原因。

第三本(是的,第三本)

另一方面,C++不同于C的一个关键地方就在于,C++在完全保留有C的高效的基础上,增添了抽象机制。而所谓的“现代C++风格”便是倡导正确利用C++的抽象机制和这些机制构建出来的现代C++库(以STL为代表)的,Bjarne也很早就倡导将C++当作一门不同于C的新语言来学习(就拿内存管理来说,使用现代C++的内存管理技术,几乎可以完全避免new和delete),因此,一本从这个思路来介绍C++的入门书籍是非常必要的——这就是推荐《Accelerated C++》的原因(以下简称AC++)。《Accelerated C++》的作者Andrew Koenig是C++标准化过程中的核心人物之一。

第二本

C++是在C语言大行其道的历史背景下发展起来的,在一开始以及后来的相当长一段时间内,C++是C的超集,所有C的特性在C++里面都有,因此导致了大量后来的C++入门书籍都从C讲起,实际上,这是一个误导,因为C++虽然是C的超集,然而用抽象机制扩展C语言的重大意义就在于用抽象去覆盖C当中裸露的种种语言特性,让程序员能够在一个更自然的抽象层面上编程,比如你不是用int

Fiber Optic Distribution Box

Outdoor Fibre Termination Box,Fiber Optic Distribution Cabinet,Wall Mount Fiber Distribution Box,Distribution Box Fiber Optic

Ningbo Fengwei Communication Technology Co., Ltd , https://www.fengweicommunication.com

Posted on