Read an Excerpt
A successful book is not made of what is in it, but what is left out of it.
—Mark Twain...as simple as possible, but no simpler.
—Albert Einstein...a writer who questions the capacity of the person at the other end of the line is not a writer at all, merely a schemer.
When he took over the editorship of the late C++ Report, the quick Herb Sutter asked me to write a column on a topic of my choosing. I agreed, and I chose to call the column “Common Knowledge.” It was supposed to be, in Herb’s words, “a regular summary of basic lore that every working C++ programmer should know—but can’t always.” After a couple of columns in that vein, however, I became interested in template metaprogramming techniques, and the topics treated in “Common Knowledge” from that point on were far from common.
However, the problem in the C++ programming industry that motivated my original choice of column remains. I commonly encounter the following types of individuals in my training and consulting work:
- Domain experts who are expert C programmers but who have only basic knowledge of (and perhaps some animosity toward) C++
- Talented new hires direct from university who have an academic appreciation for the C++ language but little production C++ experience
- Expert Java programmers who have little C++ experience and who have a tendency to program in C++ the way one would program in Java
- C++ programmers with several years of experience maintaining existing C++ applications but who have not been challenged to learn anything beyond the basics required for maintenance
I want to be immediately productive, but many of the people with whom I’m working or who I’m training require preliminary education in various C++ language features, patterns, and coding techniques before we can get down to business. Worse, I suspect that most C++ code is written in ignorance of at least some of these basics and is therefore not what most C++ experts would consider to be production quality.
This book addresses this pervasive problem by providing essential, common knowledge that every professional C++ programmer needs to know, in a form that is pared to its essentials and that can be efficiently and accurately absorbed. Much of the information is already available from other sources or is part of that compendium of unwritten information that all expert C++ programmers know. The advantage is that this material resides in one place and was selected according to what my training and consulting experience over many years has shown are the most commonly misunderstood and most useful language features, concepts, and techniques.
Perhaps the most important aspect of the sixty-three short items that make up this book is what they leave out, rather than what they contain. Many of these topics have the potential to become complex. An author’s ignorance of these complexities could result in an uninformed description that could mislead the reader, but an expert discussion of a topic in its full complexity could inundate the reader. The approach used here is to filter out needless complexity in the discussion of each topic. What remains, I hope, is a clear distillation of the essentials required for production C++ programming. C++ language wonks will recognize, therefore, that I’ve left out discussion of some issues that are interesting and even important from a theoretical perspective, but the ignorance of which does not commonly affect one’s ability to read and write production C++ code.
Another motivation for this book came as I was engaged in conversation with a group of well-known C++ experts at a conference. There was a general pall or depression among these experts that modern C++ is so complex that the “average” programmer can no longer understand it. (The specific issue was name binding in the context of templates and namespaces. Yes, getting worked up about such a topic does imply the need for more play with normal children.) On reflection, I’d have to say our attitude was pretentious and our gloom unwarranted. We “experts” have no such problems, and it’s as easy to program in C++ as it is to speak a (vastly more complex) natural language, even if you can’t diagram the deep structure of your every utterance. A recurring theme of this book is that while the full description of the minutia of a particular language feature may be daunting, day-to-day use of the feature is straightforward and natural.
Consider function overloading. A full description occupies a large chunk of the standard and whole or multiple chapters in many C++ texts. And yet, when faced with
void f( int );
void f( const char
f( "Hello" );
not a single practicing C++ programmer will be unable to determine which f is called. Full knowledge of the rules by which a call to an overloaded function is resolved is useful but only rarely necessary. The same applies to many other ostensibly complex areas of C++ language and idiom.
This is not to say that all the material presented here is easy; it’s “as simple as possible, but no simpler.” In C++ programming, as in any other worthwhile intellectual activity, many important details can’t be written on an index card. Moreover, this is not a book for “dummies.” I feel a great deal of responsibility to those who grant a portion of their valuable time to reading my books. I respect these readers and try to communicate with them as I would in person to any of my colleagues. Writing at an eighth-grade level to a professional isn’t writing. It’s pandering.
Many of the book’s items treat simple misunderstandings that I’ve seen over and over again, which just need to be pointed out (for example, scope order for member function lookup and the difference between overriding and overloading). Others deal with topics that are in the process of becoming essential knowledge for C++ professionals but are often incorrectly assumed to be difficult and are avoided (for example, class template partial specialization and template template parameters). I’ve received some criticism from the expert reviewers of the manuscript that I’ve spent too much space (approximately one third of the book) on template issues that are not really common knowledge. However, each of these experts pointed out one, two, or several of the template topics they thought did belong in the book. The telling observation is, I think, that there was little overlap among these suggestions, and every template-related item had at least one supporter.
This is the crux of the issue with the items that make up this book. I don’t expect any reader to be ignorant of every item’s topic, and it’s likely that some readers will be familiar with all of them. Obviously, if a reader is not familiar with a particular topic, there would be (I presume) some benefit in reading about it. However, even if a reader is already familiar with a topic, I’d hope that reading about it from a new perspective might clear up a slight misunderstanding or lead to a deeper understanding. This book may also have a role in saving the more experienced C++ programmer precious time. Competent C++ programmers often find themselves (as described previously) answering the same questions over and over again to the detriment of their own work. I’d suggest that the approach of “read this first, and then let’s talk” would save these C++ gurus countless hours and direct their expertise instead to the complex problems for which it’s really needed.
I initially tried to group these sixty-three items into neat chapters, but the items had other ideas. They instead tended to clump themselves together in ways that ranged from the obvious to the unexpected. For example, the items related to exceptions and resource management form a rather natural group. Less obviously, the items Capability Queries, Meaning of Pointer Comparison, Virtual Constructors and Prototype, Factory Method, and Covariant Return Types are strongly and somewhat surprisingly interrelated and are best grouped in close proximity to each other. Pointer Arithmetic decided to hang with Smart Pointers rather than with the pointer and array material earlier in the book. Rather than attempt to impose an arbitrary chapter structure on these natural groupings, I decided to grant the individual items freedom of association. Of course, many other interrelationships exist among the topics treated by the items than can be represented in a simple linear ordering, so the items make frequent internal references among themselves. It’s a clumped but connected community.
While the main idea is to be brief, discussion of a topic sometimes includes ancillary details that are not directly related to the subject at hand. These details are never necessary to follow the discussion, but the reader is put on notice that a particular facility or technique exists. For instance, the Heap template example that appears in several items informs the reader in passing about the existence of the useful but rarely discussed STL heap algorithms, and the discussion of placement new outlines the technical basis of the sophisticated buffer management techniques employed by much of the standard library. I also try to take the opportunity, whenever it seems natural to do so, to fold the discussion of subsidiary topics into the discussion of a particular, named item. Therefore, RAII contains a short discussion of the order of constructor and destructor activation, Template Argument Deduction discusses the use of helper functions for specializing class templates, and Assignment and Initialization Are Different folds in a discussion of computational constructors. This book could easily have twice the number of items, but, like the clumping of the items themselves, correlation of a subsidiary topic with a specific item puts the topic in context and helps the reader to absorb the material efficiently and accurately.
I’ve reluctantly included several topics that cannot reasonably be treated in this book’s format of short items. In particular, the items on design patterns and the design of the standard template library are laughably short and incomplete. Yet they make an appearance simply to put some common misconceptions to rest, emphasize the importance of the topics, and encourage the reader to learn more.
Stock examples are part of our programming culture, like the stories that families swap when they gather for holidays. Therefore, Shape, String, Stack, and many of the other usual suspects put in an appearance. The common appreciation of these baseline examples confers the same efficiencies as design patterns in communication, as in “Suppose I want to rotate a Shape, except...” or “When you concatenate two Strings...” Simply mentioning a common example orients the conversation and avoids the need for time-consuming background discussion. “You know how your brother acts whenever he’s arrested? Well, the other day...”
Unlike my previous books, this one tries to avoid passing judgment on certain poor programming practices and misuses of C++ language features; that’s a goal for other books, the best of which I list in the bibliography. (I was, however, not entirely successful in avoiding the tendency to preach; some bad programming practices just have to be mentioned, even if only in passing.) The goal of this book is to inform the reader of the technical essentials of production-level C++ programming in as efficient a manner as possible.
—Stephen C. Dewhurst Carver, Massachusetts January 2005