Title: C++ Programmer's Guide to the Standard Template Library
Author: Mark Nelson
Publisher: IDG Books Worldwide, 1995.
Pages: 875, softcover, with disk
Price: $49.99 US, $69.99 Canadian
ISBN: 1-56884-314-3Title: STL Tutorial and Reference Guide; C++ Programming With the Standard Template Library
Authors: David R. Musser and Atul Saini
Publisher: Addison-Wesley Publishing Company, Inc., 1996.
Pages: 400, hardcover
Price: $35.95
ISBN: 0-201-63398-1
Introduction
Nothing beats reading a good book for learning a new technology, such as C++'s Standard Template Library (STL). I've read two good books on STL recently, and they both have their selling points. Hopefully, you can afford to get both; but if you can't, this comparative review may help you decide between the two.
Nelson's Book
This book covers the philosophy, use, and intimate details of Hewlett-Packard's (HP) STL implementation. This is a large book, and as with any other large book, one of the first questions I ask is, "Does it really need to be that big?" In this case, I say "Yes." The reason is that, in my view, Nelson's book is really three distinct, complete, and mutually complementary books in one. The first part is actually a long essay (80 pages) which gives an overview of STL. The second is a standard tutorial/reference combination. The third part reproduces the HP STL Specification. In light of STL's almost experimental nature, this last part is closer to being a necessity than just a nice touch. Below, I review each of the three "sub-books" separately.
The book devotes much space to exploring the inner workings of STL, so you really need a good foundation in C/C++ to make sense of it easily. Beginners may still want to read this book, though, for three reasons: 1. STL tutorials are still scarce; 2. Beginners can ignore these explorations and still learn the essentials of STL with this book; and 3. Any beginners reading this magazine and interested in STL have a good chance of advancing beyond the beginner stage, so the book will eventually become more useful to them.
Book 1: An STL Overview
The first "book" presents an overview of STL, including its history and philosophy.
Instead of providing the usual quick recap of well-known history, Nelson first thoroughly examines the history that led up to the creation of STL. He starts by discussing the limited genericity possible in C, works his way through C++'s evolving feature set, and ends up at C++'s recent features that make a truly generic and fast library like STL possible.
He then discusses templates. If you already understand C++ templates, you can safely skip this part. For those who can't skip it, rest assured that it's a top-notch discussion of templates as they apply to STL.
Finally, Nelson gives a nickel tour of STL itself, touching on all of STL's major features.
This first book can stand alone to serve as an "STL tasting booth" for those who still haven't decided that STL is something worth learning. If you already know you want to learn STL, this part makes a nice preview for the rest of the book.
Book 2: The STL Tutorial and Reference
The second section is what we might have expected the entire book to be: first a tutorial, then a well-written reference to STL. Indeed, some STL works dedicate the whole book to tutorial and reference. But this second "sub-book" is actually a cut above the rest of the pack. I discuss the tutorial and reference parts in turn.
The tutorial starts with the major sequential container classes: vector, deque, and list, as well as the container adaptors that can make a sequential container look like a stack, queue, or priority queue.
An average book would simply have shown how to use the containers by way of a few examples. What makes this a great book is that after it shows you how to use the container, it shows how HP's STL version really works. Nelson illustrates his explanations with snippets from the HP STL source code as well as clear diagrams.
One of the great things about STL is that it implements each major container in a different way, so that each has its unique performance properties. Accordingly, the next two chapters unveil the very different inner workings of the deque and list containers.
With this detailed treatment the reader can appreciate the underlying mechanisms, which is helpful in making design decisions. It's certainly nice to know that deques perform well when adding elements to both ends, while vectors are only quick for tail insertions. But knowing why these things are so gives you a sure feeling when making design decisions. Nelson puts the topping on this sundae of sequential container information by pitting all three containers against one another. This "showdown" of containers demonstrates the space and time tradeoffs clearly.
The next chapter briefly covers STL's container adaptors. Adaptors give a container an interface more appropriate to the task at hand. One common use is turning a vector into a stack, for example.
The next chapter covers STL's four associative containers. As in previous chapters, Nelson covers the implementation underlying the containers, which in this case is a red-black tree. While the explanation is useful, I wonder if the book wouldn't be improved by covering the interface and use of the red-black tree class itself. It seems to me that users may find themselves wanting to derive their own classes from STL's version instead of writing their own.
The next two chapters in the second section cover allocators and iterators, which provide uniform memory management and access to the containers. These chapters cover the subject well, but I can't say it's one that is all that exciting to me. These chapters aren't boring, but aside from being as complete as the rest of the book, they aren't otherwise noteworthy. Maybe those wanting to do things like database and special memory access through custom allocators and iterators will find this chapter more indispensable.
The next chapter gives a very brief overview of STL's algorithms. It basically just tells you what's available so you can find more information in the reference section. Last but not least, Nelson discusses function objects. These clever object-oriented replacements for function pointers are key to many portions of STL.
The final chapters of the second section are a reference for STL, and as far as I've been able to tell, cover everything in HP STL. In addition to expanding upon the tutorial's topics, the reference covers sorting and searching, as well as set, heap, sequence, basic numeric, and miscellaneous operations.
Book 3: The STL Specification
This final "book" is a reprint of the original HP STL specification. This section is also quite valuable; it gives you an "STL bible" to refer to when your questions and problems outstrip the rest of the book's scope.
Criticisms and Kudos
Although I really like the book, I should point out a few of the book's faults and tradeoffs. The first tradeoff to keep in mind is that (probably due to timing issues) the book covers HP STL, which the pages of this magazine have shown to be very different from the emerging draft Standard STL. A serious fault is that the text rarely refers to the STL header files, so it's harder than it should be to find out which headers to include to get particular STL facilities.
The book more than makes up for these problems, however, with some really nice touches that make it truly great. For example, Nelson lists what each of the containers require of their contained objects. Documentation of this sort is dear to me, as I've frequently been forced to do without it.
As another nice touch, Nelson hints at many possibilities for extending STL through objects such as custom iterators and allocators that use something other than the heap for storage. If you wonder what this non-heap storage might be, Nelson provides some examples: database access and "special" memory access like MS-DOS's EMS memory.
Nelson minimizes the book's bulk through a form of reuse: he uses a single code example to illustrate a series of points in turn.
Finally, the chapter on associative containers attempts to shed some light on why STL's creators chose to implement associative containers as red-black trees instead of hash-based structures. His argument may not end the debate, but he does illuminate the issues well.
Other Considerations
As its back cover indicates, the book focuses on PC compilers, but readers should find it easy to identify and compensate for its few minor platform dependencies. For example, the code samples each have a commented #define at the top to make them compile with Borland C++ 4.x. These are easily removed. Another PCism: when the book displays pointers, they are clearly of the 16-bit, "short" variety. Beyond these sorts of things, I believe the code should be portable to any STL-compatible compiler (with the caveat that the diskette is MS-DOS-formatted.)
Musser and Saini's Book
As I hinted in the previous review, I expect a book of this kind to consist of two main parts, a tutorial in the basic-to-intermediate material first, and a complete reference second. Musser and Saini follow this well-established formula.
As you might expect from its (hard) cover, this book takes a more formal approach than Nelson's. It's certainly not from the ivory tower, but this book has the standard properties of a formal work: no light conversational humor in headings and text, lots of Big-O notation, and platform independent discussions. If it had a lighter writing style, it might be easier to read, but more formal writing has its advantages, too. For example, it's easier to skim the book by glancing at headings, because you don't have to mentally translate their meanings.
The book does not attempt to teach the use of templates, so readers will need to know how to use others' templates before tackling this book.
A note on accuracy: authors are only human, so they make mistakes. Addison-Wesley recognizes this and thus makes its errata sheets easily available. The errata sheet for this book is available on the Web at http://www.cs.rpi.edu/~musser/stl-book-errata.html.
The Tutorial
Musser and Saini get right to their subject. Unlike Nelson, they don't try to "sell" you on STL first; if you bought the book, they assume that you really do want to learn STL. They also don't bother recounting the converging histories of STL and C++. I give Musser and Saini points for a better overview of STL, though -- they provide less trivial examples and more of them.
The tutorial is one place where the book's theoretical outlook becomes obvious: the first tutorial chapter is on iterators, the glue that binds everything else together. Notwithstanding my lack of excitement about iterators (see previous review) I think this may be a better strategy than Nelson's. Without a good understanding of iterators, fitting STL algorithms and containers together can be quite frustrating.
The next chapter is on STL's algorithms. It might seem more prudent to cover containers next -- after all, how can you use algorithms without containers? But you can illustrate a lot of algorithms with simple vectors, which is what the authors do. Also, the basics of vectors were covered in the introductory material. The chapter actually covers all of STL's algorithms well, and with each algorithm (or group of closely related algorithms) it includes a well-chosen example program as illustration.
Next come STL's sequential containers, all in one chapter. This arrangement makes sense because the three sequential containers belong to a "family of abstractions," which lets the authors describe only once a feature common to all of the containers. The next chapter covers associative containers in much the same manner.
The next four chapters quickly cover function objects and the various adaptor types. It is interesting to note that this book considers the adaptors separately from the facilities they adapt, whereas Nelson deals with them side-by-side.
The Example Programs
Again, Musser and Saini outdo Nelson in the examples category: each of the next four chapters is built around a largish example (as compared to the rest of the text's examples) that solves a problem by using STL. We usually like to read an example that does a lot for its size, and the authors succeed handily in creating such an example here. All of the programs are also based on a common theme, working with anagrams; as a result, they all hang together well, and between programs improvements follow a natural progression.
The next chapter focuses on defining an iterator class. This is a nice, mildly evangelistic touch on the authors' part -- evangelistic because they're (naturally) trying to prove the extensibility of STL.
They then take a quick step out of the classroom and into the "real world." Here the authors discuss some of the how-to issues that come up when trying to get STL to do some nonobvious things. One of the examples show how to reduce the template code bloat problem with a novel application of polymorphism.
The Reference
The book's reference section is, like the rest of the book, quite "standard." It is divided into chapters roughly parallel to the tutorial's, and each subsection discusses the details of a particular facility. I didn't find it lacking in any way. One thing covered in this section that isn't covered in the tutorial are allocators. The reference provides enough information to let you write your own allocators if the necessity presents itself.
Criticisms and Kudos, Part 2
I do have a criticism of the book. I'm really unimpressed with the illustrations in this book. They're not inaccurate, but they just don't communicate their information as well as Nelson's do. Fortunately, I think this book doesn't need illustrations as much as Nelson's book does, so it doesn't suffer all that much. I still think that they could have been clearer, though.
Now here are some nice touches: though the rest of the book uses the HP reference implementation of STL in its examples, the introduction to the book does explain the header changes that the ISO C++ committee made. These particular changes will probably cause some headaches, and this feature should help alleviate the suffering.
The tutorial chapter on iterators offers a table of containers paired with the iterators they return. This makes matching up containers with compatible algorithms easier.
The chapter on associative containers doesn't spend much time arguing for red-black trees over hash tables, but the book does mention that there are STL-based hash containers available from the main STL site (ftp://butler.hpl.hp.com/stl), which was a nice revelation. The other sites mentioned in the same appendix are also worth a visit, and their inclusion is yet another nice touch.
Comparing the Two Books
These two books differ in philosophy, in a couple of fundamental ways. For one thing, Nelson's book tries to do more than Musser and Saini's does. Besides the reprint of the STL spec, the main extra Nelson offers is a running exploration into the workings and design of an implementation of STL. However, in doing so, he constrains the book somewhat to one implementation and one platform.
On the other hand, Nelson's coverage gives us an insight into STL that, once obtained, is hard to imagine doing without. This added insight gives the designer in all of us information to help us choose between similar STL facilities, as well as some good lessons in design. Plus, it's really easy to step past the dependencies if they get in your way. In all likelihood, future implementations of STL will look much like the HP reference implementation, and the PC dependencies are easy to spot and fix.
It all adds up to this: I think Nelson's book is a great introduction to the library, and that it provides an insight into some of the "Zen" of STL, which Musser and Saini's book does not. Also, Nelson's inclusion of the STL spec and a decent reference makes his book useful beyond the initial learning period.
Does that mean the other book is useless? No, not by any means. It's just different. For one thing, I think that Musser and Saini have done a better job of organizing their book. The organization of Nelson's book is okay, but I get the impression it wouldn't be as easy to use as a reference. By better organization I mean that it is easier to predict where to find coverage of a certain feature in Musser and Saini. In particular, Musser and Saini make a clear separation between the straight reference material and the tutorial material. Of course, Nelson's organization has its points as well: his reference section contains examples as well as the tutorial, which is nice when you're still learning how to use something and need both reference and example material at the same time.
I mentioned that Nelson's book covers a working implementation of STL. I personally consider this a plus, but perhaps not everyone will. If you don't have the time or inclination to understand the details of an STL implementation, you may be better off with Musser and Saini.
The Verdict
I think Nelson's book makes a better tutorial, and that Musser and Saini have the better reference.
If you're a non-PC user who can't stand PCisms, stay away from the Nelson book. If you're more interested in the theory of STL, start with Musser and Saini's book.
I'd really hate to choose between the two books. But if you must, I'd recommend doing what I did, if you can: learn with Nelson, and if you decide you need better reference or how-to material, get the Musser and Saini book.
Warren Young is a software engineer for Educational Technology Resources, Inc. He has been programming and playing with computers since the mid-80's. He has some web pages about programming (including STL) at http://www.cyberport.com/~tangent/programming. You can send him email at tangent@cyberport.com.