Here are some of the books which we've found useful or interesting:
Stroustrup has a slight advantage over other writers on C++: as the originator of the language he can not only tell you what the language is, he can tell you why it is. In addition he is a good technical writer, with plenty of clear explanations, and a comprehensive index. This isn't quite as well written as the second edition (co-authored with Margaret Ellis), but due to changes in the C++ language this is the edition you need to own.
The coverage of the Standard Template Library (STL) is good, although nowhere near as good as the coverage in Josuttis. It also omits Locales, although you can download the missing Appendix D covering locales as well as an Appendix E covering STL exception handling from the author's web site.
There's a lot of good writing in blogs on the web. Unfortunately there is a lot of dross and trivia out there too. Who has time to find the good stuff?
The answer, fortunately for us, appears to be Joel Spolsky. This book contains selected essays (mostly taken from blogs) on the human side of software development. There are well-written essays on such topics as management, recruitment, testing, compensation, user interfaces, etc. Included are some excellent insights into why organizations do what they do, and why things are they way that they are.
Joel Spolsky is an excellent writer — indeed, I was surprised not to find one of his own essays in the book. However, if this book has a weakness it is that Spolsky's editorial introductions and footnotes (while very interesting) sometimes overwhelm the essays themselves.
Sometimes it feels that there isn't any intelligent life out there on the web. This book is a useful reminder that there is intelligent life out there: it's just very hard to find.
Looking for a good present for someone who enjoys debugging? Or just looking to improve your debugging skills? Oualline's book is a combination of debugging puzzles and computer anecodotes. Puzzles range from the trivial (missed initialization, missing close comment), through to the more difficult (race conditions, compiler optimization induced failures). Each puzzle comes with hints and answers. However, you really have to work through each chapter in sequence as each puzzle (and each joke) tends to build upon what has gone before.
The problems, of course, have to be a lot simpler than many of those we encounter in the real world. Think of this as something along the lines of a Five Minute Mysteries for programmers rather than a Warren Commission Report. An ideal book to read in your smallest room!
If you haven't been tracking the evolution of the C++ language closely, you may have missed out on the development of templates and the introduction of the Standard Template Library (STL). With these tools you can finally program at a high level of abstraction, and C++ can finally be considered a high level language.
Josuttis provides an excellent guide to both the philosophy and usage of the C++ Standard Template Library (STL). I never really understood the full capabilities of the library (or why it was designed the way it was) until I read this book. It gives good examples of almost every usage, enough background to understand the reasoning behind the design of the library, and organizes the material very well for instant reference. It's my preferred reference for the standard template library: I use it frequently.
This is a book all professional C++ programmers should read even if it does give them the answers to some of my favorite C++ interview questions. Meyers provides 50 bullet points for writing better C++ programs. This isn't normally a format I like (too much like 10 ways to start losing weight now), but these are surprisingly good points. It contains some good material on C usages which should not be promulgated into C++, as well as the answer to the question When must you use a virtual destructor? which trips up far too many interview candidates.
Normally I'm not in favor of sequels. Nor books of lists. But More Effective C++ contains 35 good additional points. This book is more concerned with useful techniques than style or coding rules. I find it particularly helpful in designing classes which prevented naive forms of bad usage. There's good sections here on smart pointers, the correct usage of multiple inheritance, and general good object-oriented abstraction. I especially liked the explanation of how to write a class which can distinguish between its use as an lvalue (left hand side of an assignment) and an rvalue (right hand side of assignment, etc.)
We all know that we should write readable code, and we've all been cursed when faced with reading somebody else's monstrosity (or even sometimes one of own). However, there are surprisingly few books on the subject.
Towards the end of the book, I thought initially that the book seemed to be delving too far into specific structured programming techniques. But then I remembered that structured programming techniques were the answer invented to deal with unreadable code, and this line of approach didn't seem unreasonable.
It's not a reference book. It's a quick read, and you will probably read this book once or twice and (hopefully) learn something from it rather than retain it as a reference book for future use.
It's often tempting to ignore program optimization: modern CPU's are fast enough that for applications which involve trivial amounts of computation, optimization is rarely necessary.
However, for scientific and technical computing, where computations can take hours or days to complete, or for applications involving media processing, optimization is essential. Once an efficient algorithms has been chosen, the next problem is to get that algorithms to run as fast as possible on a modern computer architecture. This is where this book comes into its own.
The author, Darryl Grove, provides a good overview of of modern multi-core computer architectures, and in particular the trade-offs associated with multiple cores, multiple threads, and multiple caches. He then explains how these impact the efficiency of programs, and how simple changes to program code and data structures can cause a program to run significantly more or less efficiently on a given architecture.
One thing I particularly liked about this book is that it recognizes the strengths and weaknesses of current compilers: it is increasingly rare that an assembler programmer can outdo the performance of compiler produced code, and the maintainability of such code (as well as its portability) is often suspect. However, optimizing compilers have their limitations and require hints and language extensions to be able to make effective use of available parallelism.
A good section of the book therefore covers OpenMP, a widely implemented set of features/pragmas available in C, C++ and other languages which enable a program to be optionally parallelized for improved performance while still preserving the ability to revert to single threaded mode. (OpenMP features are available in Microsoft Visual C++ compilers, as well as in the open source gcc compiler). Before reading this book, I wasn't aware how easy OpenMP makes parallelizing many common computations. In particular, there is a good section demonstrating how the addition of a single pragma can distribute the execution of a for loop across multiple threads and, in the cases considered, provide near linear speed-ups up to the number of cores available.
The section on locks and synchronization provides some cautionary examples of unintentional race conditions for create-your-own lock schemes. (Tip: compiler optimization and code re-ordering may and probably will totally destroy your intended semantics) , and a good overview is provided of the wide variety of primitives available in Windows, OS X, Solaris, and Linux.
Finally there is a good section on the constraints to application scaling, including the use of library code, hardware constraints, and operating system constraints.
I would therefore highly recommend this book if you need to write compute-intensive code which will run in a multi-core environment.
When writing SQL its quite common to "steal" somebody else's example: but is that example a good example or a bad example? Is it efficient? Will it scale? Or will it cause problems with the database structure later on? Without a reasonable knowledge of SQL in practice, it's quite difficult to tell good examples from bad examples.
Bill Karwin's book examines "antipatterns" for SQL — code that is commonly used but generally shouldn't be. He outlines cases where the antipattern is a legitimate approach, as well as alternative solutions which will eliminate some of the problems which the original code creates.
If it's only to learn the best ways to choose a random record from a large data set (SELECT * FROM table ORDER BY RAND() LIMIT 1 isn't one of them), then it's worth reading this book.
I needed a book which would tell me enough about C# to know whether it was worth learning more, but didn't treat me as an idiot. This book proved to be it.
This is an introduction to the language (and runtime) designed for a C++, Visual Basic, or Java programmer. It explains the key concepts at a reasonable level of detail (not too high, not too low).
This book isn't a reference. It is not a complete description of the language, not is it intended as one. You'll probably therefore read it once, then refer back to it a few times before moving on to a more comprehensive tome.