“Scott Meyers’ book, Effective C++, Third Edition, is distilled programming experience — experience that you would otherwise have to learn the hard way. This book is a great resource that I recommend to everybody who writes C++ professionally.”
— Peter Dulimov, ME, Engineer, Ranges and Assessing Unit, NAVSYSCOM, Australia“The third edition is still the best book on how to put all of the pieces of C++ together in an efficient, cohesive manner. If you claim to be a C++ programmer, you must read this book.”
— Eric Nagler, Consultant, Instructor, and author of Learning C++“The first edition of this book ranks among the small (very small) number of books that I credit with significantly elevating my skills as a ‘professional’ software devel-oper. Like the others, it was practical and easy to read, but loaded with important advice. Effective C++, Third Edition, continues that tradition. C++ is a very powerful programming language. If C gives you enough rope to hang yourself, C++ is a hard-ware store with lots of helpful people ready to tie knots for you. Mastering the points discussed in this book will definitely increase your ability to effectively use C++ and reduce your stress level.”
— Jack W. Reeves, Chief Executive Officer, Bleading Edge Software Technologies“Every new developer joining my team has one assignment — to read this book.”
— Michael Lanzetta, Senior Software Engineer“I read the first edition of Effective C++ about nine years ago, and it immediately
became my favorite book on C++. In my opinion, Effective C++, Third Edition, remains a mustread today for anyone who wishes to program effectively in C++. We would live in a better world if C++ programmers had to read this book before writing their first line of professional C++ code.”
— Danny Rabbani, Software Development Engineer“I encountered the first edition of Scott Meyers’ Effective C++ as a struggling program-mer in the trenches, trying to get better at what I was doing. What a lifesaver! I found Meyers’ advice was practical, useful, and effective, fulfilling the promise of the title 100 percent. The third edition brings the practical realities of using C++ in serious development projects right up to date, adding chapters on the language’s very latest issues and features. I was delighted to still find myself learning something interesting and new from the latest edition of a book I already thought I knew well.”
— Michael Topic, Technical Program Manager“From Scott Meyers, the guru of C++, this is the definitive guide for anyone who wants to use C++ safely and effectively, or is transitioning from any other OO lan-guage to C++. This book has valuable information presented in a clear, concise, entertaining, and insightful manner.”
— Siddhartha Karan Singh, Software Developer
“This should be the second book on C++ that any developer should read, after a gen-eral introductory text. It goes beyond the how and what of C++ to address the why and wherefore. It helped me go from knowing the syntax to understanding the philos-ophy of C++ programming.”
— Timothy Knox, Software Developer“This is a fantastic update of a classic C++ text. Meyers covers a lot of new ground in this volume, and every serious C++ programmer should have a copy of this new edition.”
— Jeffrey Somers, Game Programmer“Effective C++, Third Edition, covers the things you should be doing when writing code and does a terrific job of explaining why those things are important. Think of it as best practices for writing C++.”
— Jeff Scherpelz, Software Development Engineer“As C++ embraces change, Scott Meyers’ Effective C++, Third Edition, soars to remain in perfect lock-step with the language. There are many fine introductory books on C++, but exactly one second book stands head and shoulders above the rest, and you’re holding it. With Scott guiding the way, prepare to do some soaring of your own!”
— Leor Zolman, C++ Trainer and Pundit, BD Software“This book is a must-have for both C++ veterans and newbies. After you have finished reading it, it will not collect dust on your bookshelf — you will refer to it all the time.”
— Sam Lee, Software Developer“Reading this book transforms ordinary C++ programmers into expert C++ program-mers, step-by-step, using 55 easy-to-read items, each describing one technique or tip.”
— Jeffrey D. Oldham, Ph.D., Software Engineer, Google“Scott Meyers’ Effective C++ books have long been required reading for new and expe-rienced C++ programmers alike. This new edition, incorporating almost a decade’s worth of C++ language development, is his most content-packed book yet. He does not merely describe the problems inherent in the language, but instead he provides unambiguous and easy-to-follow advice on how to avoid the pitfalls and write ‘effec-tive C++.’ I expect every C++ programmer to have read it.”
— Philipp K. Janert, Ph.D., Software Development Manager“Each previous edition of Effective C++ has been the must-have book for developers who have used C++ for a few months or a few years, long enough to stumble into the traps latent in this rich language. In this third edition, Scott Meyers extensively refreshes his sound advice for the modern world of new language and library features and the programming styles that have evolved to use them. Scott’s engaging writing style makes it easy to assimilate his guidelines on your way to becoming an effective C++ developer.”
— David Smallberg, Instructor, DevelopMentor; Lecturer, Computer Science, UCLA“Effective C++ has been completely updated for twenty-first-century C++ practice and can continue to claim to be the first second book for all C++ practitioners.”
— Matthew Wilson, Ph.D., author of Imperfect C++
Effective C++
Third Edition
Addison-Wesley Professional Computing SeriesBrian W. Kernighan, Consulting Editor Matthew H. Austern, Generic Programming and the STL:Using and Extending the C++Standard Template LibraryDavid R. Butenhof, Programming with POSIX®ThreadsBrent Callaghan, NFSIllustratedTom Cargill, C++ Programming StyleWilliam R. Cheswick/Steven M. Bellovin/Aviel D. Rubin, Firewalls and Internet Security, Second Edition: Repelling the Wily HackerDavid A. Curry, UNIX®System Security: AGuide for Users and System AdministratorsStephen C. Dewhurst, C++ Gotchas: Avoiding Common Problems in Coding and DesignDan Farmer/Wietse Venema, Forensic DiscoveryErich Gamma/Richard Helm/Ralph Johnson/John Vlissides, Design Patterns: Elements of Reusable Object-Oriented SoftwareErich Gamma/Richard Helm/Ralph Johnson/John Vlissides, Design Patterns CD: Elements of Reusable Object-Oriented Software Peter Haggar, Practical Java™Programming Language GuideDavid R. Hanson, C Interfaces and Implementations: Techniques for Creating Reusable SoftwareMark Harrison/Michael McLennan, Effective Tcl/Tk Programming: Writing Better Programs with Tcl and TkMichi Henning/Steve Vinoski, Advanced CORBA®Programming with C++Brian W. Kernighan/Rob Pike, The Practice of ProgrammingS. Keshav, An Engineering Approach to Computer Networking: ATM Networks, the Internet, and the Telephone NetworkJohn Lakos, Large-Scale C++ Software DesignScott Meyers, Effective C++ CD: 85 Specific Ways to Improve Your Programs and DesignsScott Meyers, Effective C++, Third Edition: 55 Specific Ways to Improve Your Programs and DesignsScott Meyers, More Effective C++: 35 New Ways to Improve Your Programs and DesignsScott Meyers, Effective STL: 50 Specific Ways to Improve Your Use of the Standard Template LibraryRobert B. Murray, C++ Strategies and TacticsDavid R. Musser/Gillmer J. Derge/Atul Saini, STLTutorial and Reference Guide, Second Edition: C++ Programming with the Standard Template LibraryJohn K. Ousterhout, Tcl and the Tk ToolkitCraig Partridge, Gigabit NetworkingRadia Perlman,Interconnections, Second Edition: Bridges, Routers, Switches, and Internetworking ProtocolsStephen A. Rago, UNIX®System V Network ProgrammingEric S. Raymond, The Art of UNIX ProgrammingMarc J. Rochkind, Advanced UNIX Programming, Second EditionCurt Schimmel, UNIX®Systems for Modern Architectures: Symmetric Multiprocessing and Caching for Kernel ProgrammersW. Richard Stevens, TCP/IP Illustrated, Volume 1: The ProtocolsW. Richard Stevens, TCP/IP Illustrated, Volume 3: TCP for Transactions, HTTP, NNTP, and the UNIX®Domain ProtocolsW. Richard Stevens/Bill Fenner/Andrew M. Rudoff, UNIX Network Programming Volume 1, Third Edition: The Sockets Networking APIW. Richard Stevens/Stephen A. Rago, Advanced Programming in the UNIX®Environment, Second EditionW. Richard Stevens/Gary R. Wright, TCP/IP Illustrated Volumes 1-3 Boxed SetJohn Viega/Gary McGraw, Building Secure Software: How to Avoid Security Problems the Right WayGary R. Wright/W. Richard Stevens, TCP/IP Illustrated, Volume 2: The ImplementationRuixi Yuan/W. Timothy Strayer, Virtual Private Networks: Technologies and SolutionsVisit www.awprofessional.com/series/professionalcomputing for more information about these titles.Effective C++
Third Edition
55 Specific Ways to Improve Your Programs and Designs
Scott Meyers
ADDISON-WESLEY
Boston • San Francisco • New York • Toronto • Montreal
London • Munich • Paris • Madrid
Capetown • Sydney • Tokyo • Singapore • Mexico City
▲▼▼
This e-book reproduces in electronic form the printed book content of Effective C++, Third Edition: 55 Specific Ways to Improve Your Programs and Designs, by Scott Meyers. Copyright © 2005 by Pearson Education, Inc. ISBN: 0-321-33487-6.
LICENSE FOR PERSONAL USE: For the convenience of readers, this e-book is licensed and sold in its PDF version without any digital rights management (DRM) applied. Purchasers of the PDF version may, for their personal use only, install additional copies on multiple devices and copy or print excerpts for themselves. The duplication, distribution, transfer, or sharing of this e-book’s content for any pur-pose other than the purchaser’s personal use, in whole or in part, by any means, is strictly prohibited. PERSONALIZATION NOTICE: To discourage unauthorized uses of this e-book and thereby allow its publication without DRM, each copy of the PDF version identifies its purchaser. To encourage a DRM-free policy, please protect your files from access by others.
Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in the original printed book and this e-book, and we were aware of a trademark claim, the designations have been printed in initial capital letters or in all capitals.The author and publisher have taken care in the preparation of the original printed book and this e-book, but make no expressed or implied warranty of any kind and assume no responsibility for errors or omis-sions. No liability is assumed for incidental or consequential damages in connection with or arising out of the use of the information or programs contained herein.
DISCOUNTS AND SITE LICENSES: The publisher offers discounted prices on this e-book when pur-chased with its corresponding printed book or with other e-books by Scott Meyers. The publisher also offers site licenses for these e-books (not available in some countries). For more information, please visit: www.ScottMeyers-EBooks.com or www.informit.com/aw.Copyright © 2008 by Pearson Education, Inc.
All rights reserved. This publication is protected by copyright, and permission must be obtained from the publisher prior to any prohibited reproduction, storage in a retrieval system, or transmission in any form or by any means, electronic, mechanical, photocopying, recording, or likewise. For information regarding permissions, write to:
Pearson Education, Inc
Rights and Contracts Department501 Boylston Street, Suite 900Boston, MA 02116Fax (617) 671-3447
E-book ISBN 13: 978-0-321-51582-7E-book ISBN 10: 0-321-51582-X
Second e-book release, April 2011 (essentially identical to the 11th Paper Printing).
For Nancy,
without whom nothingwould be much worth doing
Wisdom and beauty form a very rare combination.
—Petronius ArbiterSatyricon, XCIV
This page intentionally left blank
And in memory of Persephone,
1995–2004
This page intentionally left blank
Contents
Preface
AcknowledgmentsIntroduction
Chapter 1:Accustoming Yourself to C++
Item 1:Item 2:Item 3:Item 4:
View C++ as a federation of languages.
Prefer consts, enums, and inlines to #defines.Use const whenever possible.
Make sure that objects are initialized beforethey’re used.
xvxvii11111131726
Chapter 2:Constructors, Destructors, and
Assignment Operators
Know what functions C++ silently writes and calls.Explicitly disallow the use of compiler-generatedfunctions you do not want.
Item 7:Declare destructors virtual in polymorphic
base classes.
Item 8:Prevent exceptions from leaving destructors.
Item 9:Never call virtual functions during construction or
destruction.
Item 10:Have assignment operators return a reference to *this.Item 11:Handle assignment to self in operator=.Item 12:Copy all parts of an object.Item 5:Item 6:
3434374044485253576161
Chapter 3:Resource Management
Item 13:Use objects to manage resources.
xiiContentsEffective C++
Item 14:Think carefully about copying behavior in
resource-managing classes.
Item 15:Provide access to raw resources in
resource-managing classes.
Item 16:Use the same form in corresponding uses of new
and delete.
Item 17:Store newed objects in smart pointers in standalone
statements.
6669737578788486909498102106113113116123127134140
Chapter 4:Designs and Declarations
Item 18:Make interfaces easy to use correctly and hard to
use incorrectly.
Item 19:Treat class design as type design.
Item 20:Prefer pass-by-reference-to-const to pass-by-value.Item 21:Don’t try to return a reference when you must
return an object.
Item 22:Declare data members private.
Item 23:Prefer non-member non-friend functions to
member functions.
Item 24:Declare non-member functions when type
conversions should apply to all parameters.
Item 25:Consider support for a non-throwing swap.
Chapter 5: Implementations
Item 26:Item 27:Item 28:Item 29:Item 30:Item 31:
Postpone variable definitions as long as possible.Minimize casting.
Avoid returning “handles” to object internals.Strive for exception-safe code.
Understand the ins and outs of inlining.
Minimize compilation dependencies between files.
Chapter 6:Inheritance and Object-Oriented Design149
Item 32:Make sure public inheritance models “is-a.”Item 33:Avoid hiding inherited names.
Item 34:Differentiate between inheritance of interface and
inheritance of implementation.
Item 35:Consider alternatives to virtual functions.
Item 36:Never redefine an inherited non-virtual function.
150156161169178
Effective C++Contentsxiii
Item 37:Never redefine a function’s inherited default
parameter value.
Item 38:Model “has-a” or “is-implemented-in-terms-of”
through composition.
Item 39:Use private inheritance judiciously.Item 40:Use multiple inheritance judiciously.
180184187192199199203207212218222226233239240247252256262262263269273
Chapter 7:Templates and Generic Programming
Item 41:Understand implicit interfaces and compile-time
polymorphism.
Item 42:Understand the two meanings of typename.Item 43:Know how to access names in templatized
base classes.
Item 44:Factor parameter-independent code out of templates.Item 45:Use member function templates to accept
“all compatible types.”
Item 46:Define non-member functions inside templates
when type conversions are desired.
Item 47:Use traits classes for information about types.Item 48:Be aware of template metaprogramming.
Chapter 8:Customizing new and delete
Item 49:Understand the behavior of the new-handler.Item 50:Understand when it makes sense to replace new
and delete.
Item 51:Adhere to convention when writing new and delete.Item 52:Write placement delete if you write placement new.
Chapter 9:Miscellany
Item 53:Pay attention to compiler warnings.
Item 54:Familiarize yourself with the standard library,
including TR1.
Item 55:Familiarize yourself with Boost.
Appendix A: Beyond Effective C++
Appendix B:Item Mappings Between Second
and Third EditionsIndex
277280
This page intentionally left blank
Preface
I wrote the original edition of Effective C++ in 1991. When the timecame for a second edition in 1997, I updated the material in importantways, but, because I didn’t want to confuse readers familiar with thefirst edition, I did my best to retain the existing structure: 48 of theoriginal 50 Item titles remained essentially unchanged. If the bookwere a house, the second edition was the equivalent of fresheningthings up by replacing carpets, paint, and light fixtures.
For the third edition, I tore the place down to the studs. (There weretimes I wished I’d gone all the way to the foundation.) The world ofC++ has undergone enormous change since 1991, and the goal of thisbook — to identify the most important C++ programming guidelines ina small, readable package — was no longer served by the Items I’d es-tablished nearly 15 years earlier. In 1991, it was reasonable to as-sume that C++ programmers came from a C background. Now,programmers moving to C++ are just as likely to come from Java orC#. In 1991, inheritance and object-oriented programming were newto most programmers. Now they’re well-established concepts, and ex-ceptions, templates, and generic programming are the areas wherepeople need more guidance. In 1991, nobody had heard of design pat-terns. Now it’s hard to discuss software systems without referring tothem. In 1991, work had just begun on a formal standard for C++.Now that standard is eight years old, and work has begun on the nextversion.
To address these changes, I wiped the slate as clean as I could andasked myself, “What are the most important pieces of advice for prac-ticing C++ programmers in 2005?” The result is the set of Items in thisnew edition. The book has new chapters on resource managementand on programming with templates. In fact, template concerns arewoven throughout the text, because they affect almost everything inC++. The book also includes new material on programming in thepresence of exceptions, on applying design patterns, and on using the
xviPrefaceEffective C++
new TR1 library facilities. (TR1 is described in Item54.) It acknowl-edges that techniques and approaches that work well in single-threaded systems may not be appropriate in multithreaded systems.Well over half the material in the book is new. However, most of thefundamental information in the second edition continues to be impor-tant, so I found a way to retain it in one form or another. (You’ll find amapping between the second and third edition Items in Appendix B.)I’ve worked hard to make this book as good as I can, but I have no il-lusions that it’s perfect. If you feel that some of the Items in this bookare inappropriate as general advice; that there is a better way to ac-complish a task examined in the book; or that one or more of the tech-nical discussions is unclear, incomplete, or misleading, please tell me.If you find an error of any kind — technical, grammatical, typographi-cal, whatever — please tell me that, too. I’ll gladly add to the acknowl-edgments in later printings the name of the first person to bring eachproblem to my attention.
Even with the number of Items expanded to 55, the set of guidelinesin this book is far from exhaustive. But coming up with good rules —ones that apply to almost all applications almost all the time — isharder than it might seem. If you have suggestions for additionalguidelines, I would be delighted to hear about them.
I maintain a list of changes to this book since its first printing, includ-ing bug fixes, clarifications, and technical updates. The list is avail-able at the Effective C++ Errata web page, http://aristeia.com/BookErrata/ec++3e-errata.html. If you’d like to be notified when I update the list, Iencourage you to join my mailing list. I use it to make announcementslikely to interest people who follow my professional work. For details,consult http://aristeia.com/MailingList/.SCOTT DOUGLAS MEYERS
STAFFORD, OREGON
APRIL 2005
http://aristeia.com/
Acknowledgments
Effective C++ has existed for fifteen years, and I started learning C++about three years before I wrote the book. The “Effective C++ project”has thus been under development for nearly two decades. During thattime, I have benefited from the insights, suggestions, corrections, and,occasionally, dumbfounded stares of hundreds (thousands?) of peo-ple. Each has helped improve Effective C++. I am grateful to them all. I’ve given up trying to keep track of where I learned what, but one gen-eral source of information has helped me as long as I can remember:the Usenet C++ newsgroups, especially comp.lang.c++.moderated andcomp.std.c++. Many of the Items in this book — perhaps most — havebenefited from the vetting of technical ideas at which the participantsin these newsgroups excel.
Regarding new material in the third edition, Steve Dewhurst workedwith me to come up with an initial set of candidate Items. In Item11,the idea of implementing operator= via copy-and-swap came from HerbSutter’s writings on the topic, e.g., Item 13 of his Exceptional C++ (Ad-dison-Wesley, 2000). RAII (see Item13) is from Bjarne Stroustrup’sThe C++ Programming Language (Addison-Wesley, 2000). The idea be-hind Item17 came from the “Best Practices” section of the Boostshared_ptr web page, http://boost.org/libs/smart_ptr/shared_ptr.htm#Best-Practices and was refined by Item 21 of Herb Sutter’s More ExceptionalC++ (Addison-Wesley, 2002). Item29 was strongly influenced by HerbSutter’s extensive writings on the topic, e.g., Items 8-19 of ExceptionalC++, Items 17–23 of More Exceptional C++, and Items 11–13 of Excep-tional C++ Style (Addison-Wesley, 2005); David Abrahams helped mebetter understand the three exception safety guarantees. The NVI id-iom in Item35 is from Herb Sutter’s column, “Virtuality,” in the Sep-tember 2001 C/C++ Users Journal. In that same Item, the TemplateMethod and Strategy design patterns are from Design Patterns (Addi-son-Wesley, 1995) by Erich Gamma, Richard Helm, Ralph Johnson,and John Vlissides. The idea of using the NVI idiom in Item37 came
xviiiAcknowledgmentsEffective C++
from Hendrik Schober. David Smallberg contributed the motivationfor writing a custom set implementation in Item38. Item39’s observa-tion that the EBO generally isn’t available under multiple inheritanceis from David Vandevoorde’s and Nicolai M. Josuttis’ C++ Templates(Addison-Wesley, 2003). In Item42, my initial understanding abouttypename came from Greg Comeau’s C++ and C FAQ (http://www.comeaucomputing.com/techtalk/#typename), and Leor Zolmanhelped me realize that my understanding was incorrect. (My fault, notGreg’s.) The essence of Item46 is from Dan Saks’ talk, “Making NewFriends.” The idea at the end of Item52 that if you declare one versionof operator new, you should declare them all, is from Item 22 of HerbSutter’s Exceptional C++ Style. My understanding of the Boost reviewprocess (summarized in Item55) was refined by David Abrahams. Everything above corresponds to who or where I learned about some-thing, not necessarily to who or where the thing was invented or firstpublished.
My notes tell me that I also used information from Steve Clamage, An-toine Trux, Timothy Knox, and Mike Kaelbling, though, regrettably,the notes fail to tell me how or where.
Drafts of the first edition were reviewed by Tom Cargill, Glenn Carroll,Tony Davis, Brian Kernighan, Jak Kirman, Doug Lea, Moises Lejter,Eugene Santos, Jr., John Shewchuk, John Stasko, Bjarne Stroustrup,Barbara Tilly, and Nancy L. Urbano. I received suggestions forimprovements that I was able to incorporate in later printings fromNancy L. Urbano, Chris Treichel, David Corbin, Paul Gibson, SteveVinoski, Tom Cargill, Neil Rhodes, David Bern, Russ Williams, RobertBrazile, Doug Morgan, Uwe Steinmüller, Mark Somer, Doug Moore,David Smallberg, Seth Meltzer, Oleg Shteynbuk, David Papurt, TonyHansen, Peter McCluskey, Stefan Kuhlins, David Braunegg, PaulChisholm, Adam Zell, Clovis Tondo, Mike Kaelbling, Natraj Kini, LarsNyman, Greg Lutz, Tim Johnson, John Lakos, Roger Scott, ScottFrohman, Alan Rooks, Robert Poor, Eric Nagler, Antoine Trux, CadeRoux, Chandrika Gokul, Randy Mangoba, and Glenn Teitelbaum.Drafts of the second edition were reviewed by Derek Bosch, TimJohnson, Brian Kernighan, Junichi Kimura, Scott Lewandowski, LauraMichaels, David Smallberg, Clovis Tondo, Chris Van Wyk, and OlegZabluda. Later printings benefited from comments from DanielSteinberg, Arunprasad Marathe, Doug Stapp, Robert Hall, CherylFerguson, Gary Bartlett, Michael Tamm, Kendall Beaman, Eric Nagler,Max Hailperin, Joe Gottman, Richard Weeks, Valentin Bonnard, JunHe, Tim King, Don Maier, Ted Hill, Mark Harrison, Michael Rubenstein,Mark Rodgers, David Goh, Brenton Cooper, Andy Thomas-Cramer,
Effective C++Acknowledgmentsxix
Antoine Trux, John Wait, Brian Sharon, Liam Fitzpatrick, Bernd Mohr,Gary Yee, John O'Hanley, Brady Patterson, Christopher Peterson,Feliks Kluzniak, Isi Dunietz, Christopher Creutzi, Ian Cooper, CarlHarris, Mark Stickel, Clay Budin, Panayotis Matsinopoulos, DavidSmallberg, Herb Sutter, Pajo Misljencevic, Giulio Agostini, FredrikBlomqvist, Jimmy Snyder, Byrial Jensen, Witold Kuzminski, KazunobuKuriyama, Michael Christensen, Jorge Yáñez Teruel, Mark Davis, MartyRabinowitz, Ares Lagae, and Alexander Medvedev.
An early partial draft of this edition was reviewed by Brian Kernighan,Angelika Langer, Jesse Laeuchli, Roger E. Pedersen, Chris Van Wyk,Nicholas Stroustrup, and Hendrik Schober. Reviewers for a full draftwere Leor Zolman, Mike Tsao, Eric Nagler, Gene Gutnik, DavidAbrahams, Gerhard Kreuzer, Drosos Kourounis, Brian Kernighan,Andrew Kirmse, Balog Pal, Emily Jagdhar, Eugene Kalenkovich, MikeRoze, Enrico Carrara, Benjamin Berck, Jack Reeves, Steve Schirripa,Martin Fallenstedt, Timothy Knox, Yun Bai, Michael Lanzetta, PhilippJanert, Guido Bartolucci, Michael Topic, Jeff Scherpelz, Chris Nauroth,Nishant Mittal, Jeff Somers, Hal Moroff, Vincent Manis, BrandonChang, Greg Li, Jim Meehan, Alan Geller, Siddhartha Singh, Sam Lee,Sasan Dashtinezhad, Alex Marin, Steve Cai, Thomas Fruchterman,Cory Hicks, David Smallberg, Gunavardhan Kakulapati, DannyRabbani, Jake Cohen, Hendrik Schober, Paco Viciana, Glenn Kennedy,Jeffrey D. Oldham, Nicholas Stroustrup, Matthew Wilson, AndreiAlexandrescu, Tim Johnson, Leon Matthews, Peter Dulimov, and KevlinHenney. Drafts of some individual Items were reviewed by Herb Sutterand Attila F. Fehér.
Reviewing an unpolished (possibly incomplete) manuscript is de-manding work, and doing it under time pressure only makes it harder.I continue to be grateful that so many people have been willing to un-dertake it for me.
Reviewing is harder still if you have no background in the material be-ing discussed and are expected to catch every problem in the manu-script. Astonishingly, some people still choose to be copy editors.Chrysta Meadowbrooke was the copy editor for this book, and her verythorough work exposed many problems that eluded everyone else.Leor Zolman checked all the code examples against multiple compilersin preparation for the full review, then did it again after I revised themanuscript. If any errors remain, I’m responsible for them, not Leor.Karl Wiegers and especially Tim Johnson offered rapid, helpful feed-back on back cover copy.
xxAcknowledgmentsEffective C++
Since publication of the first printing, I have incorporated revisionssuggested by Jason Ross, Robert Yokota, Bernhard Merkle, AttilaFehér, Gerhard Kreuzer, Marcin Sochacki, J. Daniel Smith, IdanLupinsky, G. Wade Johnson, Clovis Tondo, Joshua Lehrer, T. DavidHudson, Phillip Hellewell, Thomas Schell, Eldar Ronen, KenKobayashi, Cameron Mac Minn, John Hershberger, Alex Dumov,Vincent Stojanov, Andrew Henrick, Jiongxiong Chen, Balbir Singh,Fraser Ross, Niels Dekker, Harsh Gaurav Vangani, Vasily Poshehonov,Yukitoshi Fujimura, Alex Howlett, Ed Ji Xihuang. Mike Rizzi, BalogPal, David Solomon, Tony Oliver, Martin Rottinger, Miaohua, BrianJohnson, Joe Suzow, Effeer Chen, Nate Kohl, Zachary Cohen, OwenChu, and Molly Sharp.
John Wait, my editor for the first two editions of this book, foolishlysigned up for another tour of duty in that capacity. His assistant,Denise Mickelsen, adroitly handled my frequent pestering with apleasant smile. (At least I think she’s been smiling. I’ve never actuallyseen her.) Julie Nahil drew the short straw and hence became myproduction manager. She handled the overnight loss of six weeks inthe production schedule with remarkable equanimity. John Fuller(her boss) and Marty Rabinowitz (his boss) helped out with productionissues, too. Vanessa Moore’s official job was to help with FrameMakerissues and PDF preparation, but she also added the entries toAppendix B and formatted it for printing on the inside cover. SolveigHaugland helped with index formatting. Sandra Schroeder and ChutiPrasertsith were responsible for cover design, though Chuti seems tohave been the one who had to rework the cover each time I said, “Butwhat about this photo with a stripe of that color...?” Chanda Leary-Coutu got tapped for the heavy lifting in marketing.
During the months I worked on the manuscript, the TV series Buffythe Vampire Slayer often helped me “de-stress” at the end of the day.Only with great restraint have I kept Buffyspeak out of the book.Kathy Reed taught me programming in 1971, and I’m gratified that weremain friends to this day. Donald French hired me and Moises Lejterto create C++ training materials in 1989 (an act that led to my reallyknowing C++), and in 1991 he engaged me to present them at StratusComputer. The students in that class encouraged me to write what ul-timately became the first edition of this book. Don also introduced meto John Wait, who agreed to publish it.
My wife, Nancy L. Urbano, continues to encourage my writing, evenafter seven book projects, a CD adaptation, and a dissertation. Shehas unbelievable forbearance. I couldn’t do what I do without her.From start to finish, our dog, Persephone, has been a companionwithout equal. Sadly, for much of this project, her companionship hastaken the form of an urn in the office. We really miss her.
Introduction
Learning the fundamentals of a programming language is one thing;learning how to design and implement effective programs in that lan-guage is something else entirely. This is especially true of C++, a lan-guage boasting an uncommon range of power and expressiveness.Properly used, C++ can be a joy to work with. An enormous variety ofdesigns can be directly expressed and efficiently implemented. A judi-ciously chosen and carefully crafted set of classes, functions, andtemplates can make application programming easy, intuitive, efficient,and nearly error-free. It isn’t unduly difficult to write effective C++programs, if you know how to do it. Used without discipline, however,C++ can lead to code that is incomprehensible, unmaintainable, inex-tensible, inefficient, and just plain wrong.
The purpose of this book is to show you how to use C++ effectively. Iassume you already know C++ as a language and that you have someexperience in its use. What I provide here is a guide to using the lan-guage so that your software is comprehensible, maintainable, porta-ble, extensible, efficient, and likely to behave as you expect.
The advice I proffer falls into two broad categories: general designstrategies, and the nuts and bolts of specific language features. Thedesign discussions concentrate on how to choose between differentapproaches to accomplishing something in C++. How do you choosebetween inheritance and templates? Between public and private in-heritance? Between private inheritance and composition? Betweenmember and non-member functions? Between pass-by-value andpass-by-reference? It’s important to make these decisions correctly atthe outset, because a poor choice may not become apparent untilmuch later in the development process, at which point rectifying it isoften difficult, time-consuming, and expensive.
Even when you know exactly what you want to do, getting things justright can be tricky. What’s the proper return type for assignment op-erators? When should a destructor be virtual? How should operator
2IntroductionEffective C++
new behave when it can’t find enough memory? It’s crucial to sweat
details like these, because failure to do so almost always leads to un-expected, possibly mystifying program behavior. This book will helpyou avoid that.
This is not a comprehensive reference for C++. Rather, it’s a collectionof 55 specific suggestions (I call them Items) for how you can improveyour programs and designs. Each Item stands more or less on its own,but most also contain references to other Items. One way to read thebook, then, is to start with an Item of interest, then follow its refer-ences to see where they lead you.
The book isn’t an introduction to C++, either. In Chapter2, for exam-ple, I’m eager to tell you all about the proper implementations of con-structors, destructors, and assignment operators, but I assume youalready know or can go elsewhere to find out what these functions doand how they are declared. A number of C++ books contain informa-tion such as that.
The purpose of this book is to highlight those aspects of C++ program-ming that are often overlooked. Other books describe the differentparts of the language. This book tells you how to combine those partsso you end up with effective programs. Other books tell you how to getyour programs to compile. This book tells you how to avoid problemsthat compilers won’t tell you about.
At the same time, this book limits itself to standard C++. Only fea-tures in the official language standard have been used here. Portabil-ity is a key concern in this book, so if you’re looking for platform-dependent hacks and kludges, this is not the place to find them.Another thing you won’t find in this book is the C++ Gospel, the OneTrue Path to perfect C++ software. Each of the Items in this book pro-vides guidance on how to develop better designs, how to avoid com-mon problems, or how to achieve greater efficiency, but none of theItems is universally applicable. Software design and implementation isa complex task, one colored by the constraints of the hardware, theoperating system, and the application, so the best I can do is provideguidelines for creating better programs.
If you follow all the guidelines all the time, you are unlikely to fall intothe most common traps surrounding C++, but guidelines, by their na-ture, have exceptions. That’s why each Item has an explanation. Theexplanations are the most important part of the book. Only by under-standing the rationale behind an Item can you determine whether itapplies to the software you are developing and to the unique con-straints under which you toil.
Effective C++Introduction3
The best use of this book is to gain insight into how C++ behaves, whyit behaves that way, and how to use its behavior to your advantage.Blind application of the Items in this book is clearly inappropriate, butat the same time, you probably shouldn’t violate any of the guidelineswithout a good reason.Terminology
There is a small C++ vocabulary that every programmer should under-stand. The following terms are important enough that it is worth mak-ing sure we agree on what they mean.
A declaration tells compilers about the name and type of something,but it omits certain details. These are declarations:
extern int x;
std::size_t numDigits(int number);class Widget;
template // object declaration// function declaration// class declaration// template declaration// (see Item42 for info on// the use of “typename”) Note that I refer to the integer x as an “object,” even though it’s ofbuilt-in type. Some people reserve the name “object” for variables ofuser-defined type, but I’m not one of them. Also note that the functionnumDigits’ return type is std::size_t, i.e., the type size_t in namespacestd. That namespace is where virtually everything in C++’s standard li-brary is located. However, because C’s standard library (the one fromC89, to be precise) can also be used in C++, symbols inherited from C(such as size_t) may exist at global scope, inside std, or both, depend-ing on which headers have been #included. In this book, I assume thatC++ headers have been #included, and that’s why I refer to std::size_tinstead of just size_t. When referring to components of the standard li-brary in prose, I typically omit references to std, relying on you to rec-ognize that things like size_t, vector, and cout are in std. In examplecode, I always include std, because real code won’t compile without it. based string, the number of elements in an STL container, etc.). It’salso the type taken by the operator[] functions in vector, deque, andstring, a convention we’ll follow when defining our own operator[] func-tions in Item3. Each function’s declaration reveals its signature, i.e., its parameterand return types. A function’s signature is the same as its type. In the size_t, by the way, is just a typedef for some unsigned type that C++uses when counting things (e.g., the number of characters in a char*- 4IntroductionEffective C++ case of numDigits, the signature is std::size_t (int), i.e., “function takingan int and returning a std::size_t.” The official C++ definition of “signa-ture” excludes the function’s return type, but in this book, it’s moreuseful to have the return type be considered part of the signature.A definition provides compilers with the details a declaration omits.For an object, the definition is where compilers set aside memory forthe object. For a function or a function template, the definition pro-vides the code body. For a class or a class template, the definition liststhe members of the class or template: int x; std::size_t numDigits(int number){ std::size_t digitsSoFar = 1; while ((number /= 10) != 0) ++digitsSoFar;return digitsSoFar; // object definition// function definition.// (This function returns// the number of digits// in its parameter.) } class Widget {public:Widget();~Widget();...}; template GraphNode();~GraphNode();...}; // class definition // template definition Initialization is the process of giving an object its first value. For ob-jects generated from structs and classes, initialization is performed byconstructors. A default constructor is one that can be called withoutany arguments. Such a constructor either has no parameters or has adefault value for every parameter: class A {public:A();}; class B {public: explicit B(int x = 0, bool b = true);}; // default constructor // default constructor; see below// for info on “explicit” Effective C++Introduction5 class C {public: explicit C(int x);}; // not a default constructor The constructors for classes B and C are declared explicit here. Thatprevents them from being used to perform implicit type conversions,though they may still be used for explicit type conversions: void doSomething(B bObject);B bObj1; doSomething(bObj1);B bObj2(28);doSomething(28);doSomething(B(28)); // a function taking an object of// type B // an object of type B // fine, passes a B to doSomething// fine, creates a B from the int 28// (the bool defaults to true)// error! doSomething takes a B,// not an int, and there is no // implicit conversion from int to B// fine, uses the B constructor to// explicitly convert (i.e., cast) the// int to a B for this call. (See // Item27 for info on casting.) Constructors declared explicit are usually preferable to non-explicitones, because they prevent compilers from performing unexpected(often unintended) type conversions. Unless I have a good reason forallowing a constructor to be used for implicit type conversions, Ideclare it explicit. I encourage you to follow the same policy. Please note how I’ve highlighted the cast in the example above.Throughout this book, I use such highlighting to call your attention tomaterial that is particularly noteworthy. (I also highlight chapternumbers, but that’s just because I think it looks nice.) The copy constructor is used to initialize an object with a differentobject of the same type, and the copy assignment operator is usedto copy the value from one object to another of the same type: class Widget {public:Widget(); Widget(const Widget& rhs); Widget& operator=(const Widget& rhs);...}; Widget w1;Widget w2(w1);w1 = w2; // default constructor// copy constructor // copy assignment operator// invoke default constructor// invoke copy constructor// invoke copy // assignment operator 6IntroductionEffective C++ Read carefully when you see what appears to be an assignment, be-cause the “=” syntax can also be used to call the copy constructor: Widget w3 = w2;// invoke copy constructor! Fortunately, copy construction is easy to distinguish from copy as-signment. If a new object is being defined (such as w3 in the statementabove), a constructor has to be called; it can’t be an assignment. If nonew object is being defined (such as in the “w1=w2” statement above),no constructor can be involved, so it’s an assignment. The copy constructor is a particularly important function, because itdefines how an object is passed by value. For example, consider this: bool hasAcceptableQuality(Widget w);... Widget aWidget; if (hasAcceptableQuality(aWidget)) ... The parameter w is passed to hasAcceptableQuality by value, so in thecall above, aWidget is copied into w. The copying is done by Widget’scopy constructor. Pass-by-value means “call the copy constructor.”(However, it’s generally a bad idea to pass user-defined types by value.Pass-by-reference-to-const is typically a better choice. For details, seeItem20.) The STL is the Standard Template Library, the part of C++’s standardlibrary devoted to containers (e.g., vector, list, set, map, etc.), iterators(e.g., vector Programmers coming to C++ from languages like Java or C# may besurprised at the notion of undefined behavior. For a variety of rea-sons, the behavior of some constructs in C++ is literally not defined:you can’t reliably predict what will happen at runtime. Here are twoexamples of code with undefined behavior: int *p = 0; std::cout << *p; // p is a null pointer // dereferencing a null pointer// yields undefined behavior Effective C++Introduction7 char name[] = \"Darla\";char c = name[10]; // name is an array of size 6 (don’t// forget the trailing null!) // referring to an invalid array index// yields undefined behavior To emphasize that the results of undefined behavior are not predict-able and may be very unpleasant, experienced C++ programmers of-ten say that programs with undefined behavior can erase your harddrive. It’s true: a program with undefined behavior could erase yourhard drive. But it’s not probable. More likely is that the program willbehave erratically, sometimes running normally, other times crash-ing, still other times producing incorrect results. Effective C++ pro-grammers do their best to steer clear of undefined behavior. In thisbook, I point out a number of places where you need to be on the look-out for it. Another term that may confuse programmers coming to C++ from an-other language is interface. Java and the .NET languages offer Inter-faces as a language element, but there is no such thing in C++,though Item31 discusses how to approximate them. When I use theterm “interface,” I’m generally talking about a function’s signature,about the accessible elements of a class (e.g., a class’s “public inter-face,” “protected interface,” or “private interface”), or about the ex-pressions that must be valid for a template’s type parameter (seeItem41). That is, I’m talking about interfaces as a fairly general de-sign idea. A client is someone or something that uses the code (typically the in-terfaces) you write. A function’s clients, for example, are its users: theparts of the code that call the function (or take its address) as well asthe humans who write and maintain such code. The clients of a classor a template are the parts of the software that use the class or tem-plate, as well as the programmers who write and maintain that code.When discussing clients, I typically focus on programmers, becauseprogrammers can be confused, misled, or annoyed by bad interfaces.The code they write can’t be. You may not be used to thinking about clients, but I’ll spend a gooddeal of time trying to convince you to make their lives as easy as youcan. After all, you are a client of the software other people develop.Wouldn’t you want those people to make things easy for you? Besides,at some point you’ll almost certainly find yourself in the position of be-ing your own client (i.e., using code you wrote), and at that point,you’ll be glad you kept client concerns in mind when developing yourinterfaces. 8IntroductionEffective C++ In this book, I often gloss over the distinction between functions andfunction templates and between classes and class templates. That’sbecause what’s true about one is often true about the other. In situa-tions where this is not the case, I distinguish among classes, func-tions, and the templates that give rise to classes and functions. When referring to constructors and destructors in code comments, Isometimes use the abbreviations ctor and dtor.Naming Conventions I have tried to select meaningful names for objects, classes, functions,templates, etc., but the meanings behind some of my names may notbe immediately apparent. Two of my favorite parameter names, forexample, are lhs and rhs. They stand for “left-hand side” and “right-hand side,” respectively. I often use them as parameter names forfunctions implementing binary operators, e.g., operator== and opera-tor*. For example, if a and b are objects representing rational numbers,and if Rational objects can be multiplied via a non-member operator*function (as Item24 explains is likely to be the case), the expression a * b is equivalent to the function call operator*(a, b) In Item24, I declare operator* like this: const Rational operator*(const Rational& lhs, const Rational& rhs); As you can see, the left-hand operand, a, is known as lhs inside thefunction, and the right-hand operand, b, is known as rhs. For member functions, the left-hand argument is represented by thethis pointer, so sometimes I use the parameter name rhs by itself. Youmay have noticed this in the declarations for some Widget memberfunctions on page5. Which reminds me. I often use the Widget classin examples. “Widget” doesn’t mean anything. It’s just a name I some-times use when I need an example class name. It has nothing to dowith widgets in GUI toolkits. I often name pointers following the rule that a pointer to an object oftype T is called pt, “pointer to T.” Here are some examples: Widget *pw;class Airplane;Airplane *pa; // pw = ptr to Widget// pa = ptr to Airplane Effective C++Introduction9 class GameCharacter;GameCharacter *pgc; // pgc = ptr to GameCharacter I use a similar convention for references: rw might be a reference to aWidget and ra a reference to an Airplane. I occasionally use the name mf when I’m talking about member func-tions. Threading Considerations As a language, C++ has no notion of threads — no notion of concur-rency of any kind, in fact. Ditto for C++’s standard library. As far asC++ is concerned, multithreaded programs don’t exist. And yet they do. My focus in this book is on standard, portable C++,but I can’t ignore the fact that thread safety is an issue many pro-grammers confront. My approach to dealing with this chasm betweenstandard C++ and reality is to point out places where the C++ con-structs I examine are likely to cause problems in a threaded environ-ment. That doesn’t make this a book on multithreaded programmingwith C++. Far from it. Rather, it makes it a book on C++ programmingthat, while largely limiting itself to single-threaded considerations, ac-knowledges the existence of multithreading and tries to point outplaces where thread-aware programmers need to take particular carein evaluating the advice I offer. If you’re unfamiliar with multithreading or have no need to worryabout it, you can ignore my threading-related remarks. If you are pro-gramming a threaded application or library, however, remember thatmy comments are little more than a starting point for the issues you’llneed to address when using C++.TR1 and Boost You’ll find references to TR1 and Boost throughout this book. Eachhas an Item that describes it in some detail (Item54 for TR1, Item55for Boost), but, unfortunately, these Items are at the end of the book.(They’re there because it works better that way. Really. I tried them ina number of other places.) If you like, you can turn to those Items andread them now, but if you’d prefer to start the book at the beginninginstead of the end, the following executive summary will tide you over: ■ TR1 (“Technical Report 1”) is a specification for new functionalitybeing added to C++’s standard library. This functionality takes theform of new class and function templates for things like hash ta- 10IntroductionEffective C++ bles, reference-counting smart pointers, regular expressions, andmore. All TR1 components are in the namespace tr1 that’s nestedinside the namespace std. ■ Boost is an organization and a web site (http://boost.org) offeringportable, peer-reviewed, open source C++ libraries. Most TR1functionality is based on work done at Boost, and until compilervendors include TR1 in their C++ library distributions, the Boostweb site is likely to remain the first stop for developers looking forTR1 implementations. Boost offers more than is available in TR1,however, so it’s worth knowing about in any case. 48Item 9Chapter 2 because destructors that emit exceptions are dangerous, always run-ning the risk of premature program termination or undefined behav-ior. In this example, telling clients to call close themselves doesn’timpose a burden on them; it gives them an opportunity to deal witherrors they would otherwise have no chance to react to. If they don’tfind that opportunity useful (perhaps because they believe that noerror will really occur), they can ignore it, relying on DBConn’s destruc-tor to call close for them. If an error occurs at that point — if close doesthrow — they’re in no position to complain if DBConn swallows theexception or terminates the program. After all, they had first crack atdealing with the problem, and they chose not to use it.Things to Remember ✦ Destructors should never emit exceptions. If functions called in adestructor may throw, the destructor should catch any exceptions,then swallow them or terminate the program. If class clients need to be able to react to exceptions thrown duringan operation, the class should provide a regular (i.e., non-destruc-tor) function that performs the operation. ✦ Item 9: Never call virtual functions during construction or destruction. I’ll begin with the recap: you shouldn’t call virtual functions duringconstruction or destruction, because the calls won’t do what youthink, and if they did, you’d still be unhappy. If you’re a recoveringJava or C# programmer, pay close attention to this Item, because thisis a place where those languages zig, while C++ zags. Suppose you’ve got a class hierarchy for modeling stock transactions,e.g., buy orders, sell orders, etc. It’s important that such transactionsbe auditable, so each time a transaction object is created, an appro-priate entry needs to be created in an audit log. This seems like a rea-sonable way to approach the problem: class Transaction {public: Transaction(); virtual void logTransaction() const = 0;...}; // base class for all// transactions // make type-dependent// log entry Constructors, Destructors, operator=Item 949 Transaction::Transaction(){... logTransaction();} class BuyTransaction: public Transaction {public: virtual void logTransaction() const;... }; class SellTransaction: public Transaction {public: virtual void logTransaction() const;...}; // implementation of// base class ctor// as final action, log this// transaction// derived class// how to log trans-// actions of this type // derived class// how to log trans-// actions of this type Consider what happens when this code is executed: BuyTransaction b; Clearly a BuyTransaction constructor will be called, but first, a Transac-tion constructor must be called; base class parts of derived classobjects are constructed before derived class parts are. The last line ofthe Transaction constructor calls the virtual function logTransaction, butthis is where the surprise comes in. The version of logTransaction that’scalled is the one in Transaction, not the one in BuyTransaction — eventhough the type of object being created is BuyTransaction. During baseclass construction, virtual functions never go down into derivedclasses. Instead, the object behaves as if it were of the base type.Informally speaking, during base class construction, virtual functionsaren’t. There’s a good reason for this seemingly counterintuitive behavior.Because base class constructors execute before derived class con-structors, derived class data members have not been initialized whenbase class constructors run. If virtual functions called during baseclass construction went down to derived classes, the derived classfunctions would almost certainly refer to local data members, butthose data members would not yet have been initialized. That wouldbe a non-stop ticket to undefined behavior and late-night debuggingsessions. Calling down to parts of an object that have not yet been ini-tialized is inherently dangerous, so C++ gives you no way to do it. It’s actually more fundamental than that. During base class construc-tion of a derived class object, the type of the object is that of the base 50Item 9Chapter 2 class. Not only do virtual functions resolve to the base class, but theparts of the language using runtime type information (e.g.,dynamic_cast (see Item27) and typeid) treat the object as a base classtype. In our example, while the Transaction constructor is running toinitialize the base class part of a BuyTransaction object, the object is oftype Transaction. That’s how every part of C++ will treat it, and thetreatment makes sense: the BuyTransaction-specific parts of the objecthaven’t been initialized yet, so it’s safest to treat them as if they didn’texist. An object doesn’t become a derived class object until executionof a derived class constructor begins. The same reasoning applies during destruction. Once a derived classdestructor has run, the object’s derived class data members assumeundefined values, so C++ treats them as if they no longer exist. Uponentry to the base class destructor, the object becomes a base classobject, and all parts of C++ — virtual functions, dynamic_casts, etc., —treat it that way. In the example code above, the Transaction constructor made a directcall to a virtual function, a clear and easy-to-see violation of thisItem’s guidance. The violation is so easy to see, some compilers issuea warning about it. (Others don’t. See Item53 for a discussion ofwarnings.) Even without such a warning, the problem would almostcertainly become apparent before runtime, because the logTransactionfunction is pure virtual in Transaction. Unless it had been defined(unlikely, but possible — see Item34), the program wouldn’t link: thelinker would be unable to find the necessary implementation of Trans-action::logTransaction. It’s not always so easy to detect calls to virtual functions during con-struction or destruction. If Transaction had multiple constructors, eachof which had to perform some of the same work, it would be good soft-ware engineering to avoid code replication by putting the common ini-tialization code, including the call to logTransaction, into a private non-virtual initialization function, say, init: class Transaction {public: Transaction(){ init(); } virtual void logTransaction() const = 0;...private:void init(){... logTransaction();}}; // call to non-virtual... // ...that calls a virtual! Constructors, Destructors, operator=Item 951 This code is conceptually the same as the earlier version, but it’s moreinsidious, because it will typically compile and link without complaint.In this case, because logTransaction is pure virtual in Transaction, mostruntime systems will abort the program when the pure virtual iscalled (typically issuing a message to that effect). However, if logTrans-action were a “normal” virtual function (i.e., not pure virtual) with animplementation in Transaction, that version would be called, and theprogram would merrily trot along, leaving you to figure out why thewrong version of logTransaction was called when a derived class objectwas created. The only way to avoid this problem is to make sure thatnone of your constructors or destructors call virtual functions on theobject being created or destroyed and that all the functions they callobey the same constraint. But how do you ensure that the proper version of logTransaction iscalled each time an object in the Transaction hierarchy is created?Clearly, calling a virtual function on the object from the Transactionconstructor(s) is the wrong way to do it. There are different ways to approach this problem. One is to turnlogTransaction into a non-virtual function in Transaction, then requirethat derived class constructors pass the necessary log information tothe Transaction constructor. That function can then safely call the non-virtual logTransaction. Like this: class Transaction {public: explicit Transaction(const std::string& logInfo); void logTransaction(const std::string& logInfo) const;... }; Transaction::Transaction(const std::string& logInfo){... logTransaction(logInfo);} class BuyTransaction: public Transaction {public: BuyTransaction( parameters ) : Transaction(createLogString( parameters )){ ... }...private: static std::string createLogString( parameters );}; // now a non-// virtual func // now a non-// virtual call // pass log info// to base class// constructor 52Item 10Chapter 2 In other words, since you can’t use virtual functions to call down frombase classes during construction, you can compensate by havingderived classes pass necessary construction information up to baseclass constructors instead. In this example, note the use of the (private) static function createL-ogString in BuyTransaction. Using a helper function to create a value topass to a base class constructor is often more convenient (and morereadable) than going through contortions in the member initializationlist to give the base class what it needs. By making the function static,there’s no danger of accidentally referring to the nascent BuyTransac-tion object’s as-yet-uninitialized data members. That’s important,because the fact that those data members will be in an undefinedstate is why calling virtual functions during base class constructionand destruction doesn’t go down into derived classes in the first place.Things to Remember ✦ Don’t call virtual functions during construction or destruction, be-cause such calls will never go to a more derived class than that ofthe currently executing constructor or destructor. Item 10:Have assignment operators return a reference to *this. One of the interesting things about assignments is that you can chainthem together: int x, y, z;x = y = z = 15; // chain of assignments Also interesting is that assignment is right-associative, so the aboveassignment chain is parsed like this: x = (y = (z = 15)); Here, 15 is assigned to z, then the result of that assignment (theupdated z) is assigned to y, then the result of that assignment (theupdated y) is assigned to x. The way this is implemented is that assignment returns a reference toits left-hand argument, and that’s the convention you should followwhen you implement assignment operators for your classes: class Widget {public:... 116Item 27Chapter 5 Here I’ve switched from an object of type string to an object of type Wid-get to avoid any preconceptions about the cost of performing a con-struction, destruction, or assignment for the object. In terms of Widget operations, the costs of these two approaches areas follows: ■■ Approach A: 1 constructor + 1 destructor + n assignments.Approach B: n constructors + n destructors. For classes where an assignment costs less than a constructor-destructor pair, Approach A is generally more efficient. This is espe-cially the case as n gets large. Otherwise, Approach B is probably bet-ter. Furthermore, Approach A makes the name w visible in a largerscope (the one containing the loop) than Approach B, something that’scontrary to program comprehensibility and maintainability. As aresult, unless you know that (1) assignment is less expensive than aconstructor-destructor pair and (2) you’re dealing with a perfor-mance-sensitive part of your code, you should default to usingApproach B. Things to Remember ✦ Postpone variable definitions as long as possible. It increases pro-gram clarity and improves program efficiency. Item 27:Minimize casting. The rules of C++ are designed to guarantee that type errors are impos-sible. In theory, if your program compiles cleanly, it’s not trying toperform any unsafe or nonsensical operations on any objects. This isa valuable guarantee. You don’t want to forgo it lightly. Unfortunately, casts subvert the type system. That can lead to allkinds of trouble, some easy to recognize, some extraordinarily subtle.If you’re coming to C++ from C, Java, or C#, take note, because cast-ing in those languages is more necessary and less dangerous than inC++. But C++ is not C. It’s not Java. It’s not C#. In this language, cast-ing is a feature you want to approach with great respect. Let’s begin with a review of casting syntax, because there are usuallythree different ways to write the same cast. C-style casts look like this: (T) expressionFunction-style casts use this syntax: // cast expression to be of type T// cast expression to be of type T T(expression) ImplementationsItem 27117 There is no difference in meaning between these forms; it’s purely amatter of where you put the parentheses. I call these two forms old-style casts. C++ also offers four new cast forms (often called new-style or C++-stylecasts): const_cast Each serves a distinct purpose: ■ const_cast is typically used to cast away the constness of objects. It is the only C++-style cast that can do this. ■ dynamic_cast is primarily used to perform “safe downcasting,” i.e., to determine whether an object is of a particular type in an inher-itance hierarchy. It is the only cast that cannot be performed us-ing the old-style syntax. It is also the only cast that may have asignificant runtime cost. (I’ll provide details on this a bit later.) ■ reinterpret_cast is intended for low-level casts that yield implemen-tation-dependent (i.e., unportable) results, e.g., casting a pointerto an int. Such casts should be rare outside low-level code. I use itonly once in this book, and that’s only when discussing how youmight write a debugging allocator for raw memory (see Item50). ■ static_cast can be used to force implicit conversions (e.g., non-constobject to const object (as in Item3), int to double, etc.). It can also beused to perform the reverse of many such conversions (e.g., void* pointers to typed pointers, pointer-to-base to pointer-to-derived),though it cannot cast from const to non-const objects. (Onlyconst_cast can do that.) The old-style casts continue to be legal, but the new forms are prefer-able. First, they’re much easier to identify in code (both for humansand for tools like grep), thus simplifying the process of finding placesin the code where the type system is being subverted. Second, themore narrowly specified purpose of each cast makes it possible forcompilers to diagnose usage errors. For example, if you try to castaway constness using a new-style cast other than const_cast, yourcode won’t compile. About the only time I use an old-style cast is when I want to call an ex-plicit constructor to pass an object to a function. For example: 118Item 27Chapter 5 class Widget {public: explicit Widget(int size);...}; void doSomeWork(const Widget& w);doSomeWork(Widget(15)); doSomeWork(static_cast // create Widget from int// with function-style cast// create Widget from int// with C++-style cast Somehow, deliberate object creation doesn’t “feel” like a cast, so I’dprobably use the function-style cast instead of the static_cast in thiscase. (They do exactly the same thing here: create a temporary Widgetobject to pass to doSomeWork.) Then again, code that leads to a coredump usually feels pretty reasonable when you write it, so perhapsyou’d best ignore feelings and use new-style casts all the time.Many programmers believe that casts do nothing but tell compilers totreat one type as another, but this is mistaken. Type conversions ofany kind (either explicit via casts or implicit by compilers) often lead tocode that is executed at runtime. For example, in this code fragment, int x, y;... double d = static_cast // divide x by y, but use// floating point division the cast of the int x to a double almost certainly generates code,because on most architectures, the underlying representation for anint is different from that for a double. That’s perhaps not so surprising,but this example may widen your eyes a bit: class Base { ... }; class Derived: public Base { ... };Derived d;Base *pb = &d; // implicitly convert Derived* ⇒ Base* Here we’re just creating a base class pointer to a derived class object,but sometimes, the two pointer values will not be the same. Whenthat’s the case, an offset is applied at runtime to the Derived* pointer toget the correct Base* pointer value. This last example demonstrates that a single object (e.g., an object oftype Derived) might have more than one address (e.g., its addresswhen pointed to by a Base* pointer and its address when pointed to bya Derived* pointer). That can’t happen in C. It can’t happen in Java. Itcan’t happen in C#. It does happen in C++. In fact, when multiple ImplementationsItem 27119 inheritance is in use, it happens virtually all the time, but it can hap-pen under single inheritance, too. Among other things, that meansyou should generally avoid making assumptions about how things arelaid out in C++, and you should certainly not perform casts based onsuch assumptions. For example, casting object addresses to char*pointers and then using pointer arithmetic on them almost alwaysyields undefined behavior. But note that I said that an offset is “sometimes” required. The wayobjects are laid out and the way their addresses are calculated variesfrom compiler to compiler. That means that just because your “I knowhow things are laid out” casts work on one platform doesn’t meanthey’ll work on others. The world is filled with woeful programmerswho’ve learned this lesson the hard way. An interesting thing about casts is that it’s easy to write somethingthat looks right (and might be right in other languages) but is wrong.Many application frameworks, for example, require that virtual mem-ber function implementations in derived classes call their base classcounterparts first. Suppose we have a Window base class and a Spe-cialWindow derived class, both of which define the virtual functiononResize. Further suppose that SpecialWindow’s onResize is expected toinvoke Window’s onResize first. Here’s a way to implement this thatlooks like it does the right thing, but doesn’t: class Window {public: virtual void onResize() { ... }...}; class SpecialWindow: public Window {public: virtual void onResize() { static_cast ... // base class// base onResize impl// derived class // derived onResize impl;// cast *this to Window,// then call its onResize;// this doesn’t work!// do SpecialWindow-// specific stuff }...}; I’ve highlighted the cast in the code. (It’s a new-style cast, but usingan old-style cast wouldn’t change anything.) As you would expect, thecode casts *this to a Window. The resulting call to onResize thereforeinvokes Window::onResize. What you might not expect is that it doesnot invoke that function on the current object! Instead, the cast cre- 120Item 27Chapter 5 ates a new, temporary copy of the base class part of *this, then invokesonResize on the copy! The above code doesn’t call Window::onResize onthe current object and then perform the SpecialWindow-specificactions on that object — it calls Window::onResize on a copy of the baseclass part of the current object before performing SpecialWindow-spe-cific actions on the current object. If Window::onResize modifies thecurrent object (hardly a remote possibility, since onResize is a non-const member function), the current object won’t be modified. Instead,a copy of that object will be modified. If SpecialWindow::onResize modi-fies the current object, however, the current object will be modified,leading to the prospect that the code will leave the current object in aninvalid state, one where base class modifications have not been made,but derived class ones have been. The solution is to eliminate the cast, replacing it with what you reallywant to say. You don’t want to trick compilers into treating *this as abase class object; you want to call the base class version of onResize onthe current object. So say that: class SpecialWindow: public Window {public: virtual void onResize() {Window::onResize();...}...}; // call Window::onResize// on *this This example also demonstrates that if you find yourself wanting tocast, it’s a sign that you could be approaching things the wrong way.This is especially the case if your want is for dynamic_cast. Before delving into the design implications of dynamic_cast, it’s worthobserving that many implementations of dynamic_cast can be quiteslow. For example, at least one common implementation is based inpart on string comparisons of class names. If you’re performing adynamic_cast on an object in a single-inheritance hierarchy four levelsdeep, each dynamic_cast under such an implementation could cost youup to four calls to strcmp to compare class names. A deeper hierarchyor one using multiple inheritance would be more expensive. There arereasons that some implementations work this way (they have to dowith support for dynamic linking). Nonetheless, in addition to beingleery of casts in general, you should be especially leery ofdynamic_casts in performance-sensitive code. The need for dynamic_cast generally arises because you want to per-form derived class operations on what you believe to be a derived class ImplementationsItem 27121 object, but you have only a pointer- or reference-to-base throughwhich to manipulate the object. There are two general ways to avoidthis problem. First, use containers that store pointers (often smart pointers — seeItem13) to derived class objects directly, thus eliminating the need tomanipulate such objects through base class interfaces. For example,if, in our Window/SpecialWindow hierarchy, only SpecialWindows sup-port blinking, instead of doing this: class Window { ... }; class SpecialWindow: public Window {public: void blink();...}; typedef// see Item13 for infostd::vector for (VPW::iterator iter = winPtrs.begin();// undesirable code: iter != winPtrs.end();// uses dynamic_cast++iter) { if (SpecialWindow *psw = dynamic_cast try to do this instead: typedef std::vector for (VPSW::iterator iter = winPtrs.begin();// better code: uses iter != winPtrs.end();// no dynamic_cast++iter) (*iter)->blink(); Of course, this approach won’t allow you to store pointers to all possi-ble Window derivatives in the same container. To work with differentwindow types, you might need multiple type-safe containers. An alternative that will let you manipulate all possible Window deriva-tives through a base class interface is to provide virtual functions inthe base class that let you do what you need. For example, thoughonly SpecialWindows can blink, maybe it makes sense to declare the 122Item 27Chapter 5 function in the base class, offering a default implementation that doesnothing: class Window {public: virtual void blink() {}...}; // default impl is no-op;// see Item34 for why// a default impl may be// a bad idea class SpecialWindow: public Window {public: virtual void blink() { ... }// in this class, blink...// does something}; typedef std::vector // (ptrs to) all possible ...// Window typesfor (VPW::iterator iter = winPtrs.begin(); iter != winPtrs.end();++iter)// note lack of (*iter)->blink();// dynamic_cast Neither of these approaches — using type-safe containers or movingvirtual functions up the hierarchy — is universally applicable, but inmany cases, they provide a viable alternative to dynamic_casting. Whenthey do, you should embrace them. One thing you definitely want to avoid is designs that involve cascad-ing dynamic_casts, i.e., anything that looks like this: class Window { ... };...// derived classes are defined heretypedef std::vector for (VPW::iterator iter = winPtrs.begin(); iter != winPtrs.end(); ++iter){ if (SpecialWindow1 *psw1 = dynamic_cast dynamic_cast else if (SpecialWindow3 *psw3 = dynamic_cast ...} ImplementationsItem 28123 Such C++ generates code that’s big and slow, plus it’s brittle, becauseevery time the Window class hierarchy changes, all such code has tobe examined to see if it needs to be updated. (For example, if a newderived class gets added, a new conditional branch probably needs tobe added to the above cascade.) Code that looks like this shouldalmost always be replaced with something based on virtual functioncalls. Good C++ uses very few casts, but it’s generally not practical to get ridof all of them. The cast from int to double on page118, for example, isa reasonable use of a cast, though it’s not strictly necessary. (The codecould be rewritten to declare a new variable of type double that’s ini-tialized with x’s value.) Like most suspicious constructs, casts shouldbe isolated as much as possible, typically hidden inside functionswhose interfaces shield callers from the grubby work being doneinside. Things to Remember ✦ Avoid casts whenever practical, especially dynamic_casts in perfor-mance-sensitive code. If a design requires casting, try to develop acast-free alternative. When casting is necessary, try to hide it inside a function. Clientscan then call the function instead of putting casts in their own code.Prefer C++-style casts to old-style casts. They are easier to see, andthey are more specific about what they do. ✦✦ Item 28:Avoid returning “handles” to object internals. Suppose you’re working on an application involving rectangles. Eachrectangle can be represented by its upper left corner and its lowerright corner. To keep a Rectangle object small, you might decide thatthe points defining its extent shouldn’t be stored in the Rectangleitself, but rather in an auxiliary struct that the Rectangle points to: class Point { public: Point(int x, int y);... void setX(int newVal);void setY(int newVal);...}; // class for representing points 226Item 47Chapter 7 template const Rational const Rational template const Rational const Rational { return doMultiply(lhs, rhs); }...}; // declare// helper// template // Have friend// call helper Many compilers essentially force you to put all template definitions inheader files, so you may need to define doMultiply in your header aswell. (As Item30 explains, such templates need not be inline.) Thatcould look like this: template const Rational {// header file,return Rational lhs.denominator() * rhs.denominator()); } As a template, of course, doMultiply won’t support mixed-mode multi-plication, but it doesn’t need to. It will only be called by operator*, andoperator* does support mixed-mode operations! In essence, the func-tion operator* supports whatever type conversions are necessary toensure that two Rational objects are being multiplied, then it passesthese two objects to an appropriate instantiation of the doMultiply tem-plate to do the actual multiplication. Synergy in action, no?Things to Remember ✦ When writing a class template that offers functions related to thetemplate that support implicit type conversions on all parameters,define those functions as friends inside the class template. Item 47:Use traits classes for information about types. The STL is primarily made up of templates for containers, iterators,and algorithms, but it also has a few utility templates. One of these iscalled advance. advance moves a specified iterator a specified distance: Templates and Generic ProgrammingItem 47227 template // move iter d units// forward; if d < 0,// move iter backward Conceptually, advance just does iter += d, but advance can’t be imple-mented that way, because only random access iterators support the+= operation. Less powerful iterator types have to implement advanceby iteratively applying ++ or -- d times. Um, you don’t remember your STL iterator categories? No problem,we’ll do a mini-review. There are five categories of iterators, corre-sponding to the operations they support. Input iterators can move onlyforward, can move only one step at a time, can only read what theypoint to, and can read what they’re pointing to only once. They’remodeled on the read pointer into an input file; the C++ library’sistream_iterators are representative of this category. Output iteratorsare analogous, but for output: they move only forward, move only onestep at a time, can only write what they point to, and can write it onlyonce. They’re modeled on the write pointer into an output file;ostream_iterators epitomize this category. These are the two least pow-erful iterator categories. Because input and output iterators can moveonly forward and can read or write what they point to at most once,they are suitable only for one-pass algorithms. A more powerful iterator category consists of forward iterators. Suchiterators can do everything input and output iterators can do, plusthey can read or write what they point to more than once. This makesthem viable for multi-pass algorithms. The STL offers no singly linkedlist, but some libraries offer one (usually called slist), and iterators intosuch containers are forward iterators. Iterators into TR1’s hashedcontainers (see Item54) may also be in the forward category. Bidirectional iterators add to forward iterators the ability to movebackward as well as forward. Iterators for the STL’s list are in this cat-egory, as are iterators for set, multiset, map, and multimap. The most powerful iterator category is that of random access iterators.These kinds of iterators add to bidirectional iterators the ability to per-form “iterator arithmetic,” i.e., to jump forward or backward an arbi-trary distance in constant time. Such arithmetic is analogous topointer arithmetic, which is not surprising, because random accessiterators are modeled on built-in pointers, and built-in pointers canact as random access iterators. Iterators for vector, deque, and stringare random access iterators. For each of the five iterator categories, C++ has a “tag struct” in thestandard library that serves to identify it: 228Item 47Chapter 7 struct input_iterator_tag {};struct output_iterator_tag {}; struct forward_iterator_tag: public input_iterator_tag {}; struct bidirectional_iterator_tag: public forward_iterator_tag {}; struct random_access_iterator_tag: public bidirectional_iterator_tag {}; The inheritance relationships among these structs are valid is-a rela-tionships (see Item32): it’s true that all forward iterators are alsoinput iterators, etc. We’ll see the utility of this inheritance shortly.But back to advance. Given the different iterator capabilities, one wayto implement advance would be to use the lowest-common-denomina-tor strategy of a loop that iteratively increments or decrements theiterator. However, that approach would take linear time. Randomaccess iterators support constant-time iterator arithmetic, and we’dlike to take advantage of that ability when it’s present. What we really want to do is implement advance essentially like this: template if (iter is a random access iterator) {iter += d;}else { if (d >= 0) { while (d--) ++iter; }else { while (d++) --iter; }}} // use iterator arithmetic// for random access iters// use iterative calls to// ++ or -- for other// iterator categories This requires being able to determine whether iter is a random accessiterator, which in turn requires knowing whether its type, IterT, is arandom access iterator type. In other words, we need to get someinformation about a type. That’s what traits let you do: they allow youto get information about a type during compilation. Traits aren’t a keyword or a predefined construct in C++; they’re atechnique and a convention followed by C++ programmers. One of thedemands made on the technique is that it has to work as well forbuilt-in types as it does for user-defined types. For example, if advanceis called with a pointer (like a const char*) and an int, advance has towork, but that means that the traits technique must apply to built-intypes like pointers. The fact that traits must work with built-in types means that thingslike nesting information inside types won’t do, because there’s no wayto nest information inside pointers. The traits information for a type,then, must be external to the type. The standard technique is to put it Templates and Generic ProgrammingItem 47229 into a template and one or more specializations of that template. Foriterators, the template in the standard library is named iterator_traits: template As you can see, iterator_traits is a struct. By convention, traits arealways implemented as structs. Another convention is that the structsused to implement traits are known as — I am not making this up —traits classes. The way iterator_traits works is that for each type IterT, a typedef namediterator_category is declared in the struct iterator_traits iterator_traits implements this in two parts. First, it imposes the requirement that any user-defined iterator type must contain a nestedtypedef named iterator_category that identifies the appropriate tagstruct. deque’s iterators are random access, for example, so a class fordeque iterators would look something like this: template < ... >// template params elidedclass deque {public: class iterator {public: typedef random_access_iterator_tag iterator_category;...};...}; list’s iterators are bidirectional, however, so they’d do things this way: template < ... >class list {public: class iterator {public: typedef bidirectional_iterator_tag iterator_category;...};...}; iterator_traits just parrots back the iterator class’s nested typedef: // the iterator_category for type IterT is whatever IterT says it is;// see Item42 for info on the use of “typedef typename”template typedef typename IterT::iterator_category iterator_category;...}; 230Item 47Chapter 7 This works well for user-defined types, but it doesn’t work at all foriterators that are pointers, because there’s no such thing as a pointerwith a nested typedef. The second part of the iterator_traits implemen-tation handles iterators that are pointers. To support such iterators, iterator_traits offers a partial template spe-cialization for pointer types. Pointers act as random access iterators,so that’s the category iterator_traits specifies for them: template typedef random_access_iterator_tag iterator_category;...}; At this point, you know how to design and implement a traits class: ■ Identify some information about types you’d like to make available(e.g., for iterators, their iterator category). Choose a name to identify that information (e.g., iterator_category).Provide a template and set of specializations (e.g., iterator_traits)that contain the information for the types you want to support. ■■ Given iterator_traits — actually std::iterator_traits, since it’s part of C++’sstandard library — we can refine our pseudocode for advance: template if (typeid(typename std::iterator_traits Although this looks promising, it’s not what we want. For one thing, itwill lead to compilation problems, but we’ll explore that in Item48;right now, there’s a more fundamental issue to consider. IterT’s type isknown during compilation, so iterator_traits What we really want is a conditional construct (i.e., an if...else state-ment) for types that is evaluated during compilation. As it happens,C++ already has a way to get that behavior. It’s called overloading. When you overload some function f, you specify different parametertypes for the different overloads. When you call f, compilers pick the Templates and Generic ProgrammingItem 47231 best overload, based on the arguments you’re passing. Compilersessentially say, “If this overload is the best match for what’s beingpassed, call this f; if this other overload is the best match, call it; ifthis third one is best, call it,” etc. See? A compile-time conditionalconstruct for types. To get advance to behave the way we want, all wehave to do is create multiple versions of an overloaded function con-taining the “guts” of advance, declaring each to take a different type ofiterator_category object. I use the name doAdvance for these functions: template std::random_access_iterator_tag) { iter += d;} template std::bidirectional_iterator_tag) { if (d >= 0) { while (d--) ++iter; }else { while (d++) --iter; }} template std::input_iterator_tag) { if (d < 0 ) { throw std::out_of_range(\"Negative distance\");} while (d--) ++iter;} // use this impl for// random access// iterators // use this impl for// bidirectional// iterators // use this impl for// input iterators // see below Because forward_iterator_tag inherits from input_iterator_tag, the ver-sion of doAdvance for input_iterator_tag will also handle forward itera-tors. That’s the motivation for inheritance among the variousiterator_tag structs. (In fact, it’s part of the motivation for all publicinheritance: to be able to write code for base class types that alsoworks for derived class types.) The specification for advance allows both positive and negative dis-tances for random access and bidirectional iterators, but behavior isundefined if you try to move a forward or input iterator a negative dis-tance. The implementations I checked simply assumed that d wasnon-negative, thus entering a very long loop counting “down” to zero ifa negative distance was passed in. In the code above, I’ve shown anexception being thrown instead. Both implementations are valid.That’s the curse of undefined behavior: you can’t predict what willhappen. 232Item 47Chapter 7 Given the various overloads for doAdvance, all advance needs to do iscall them, passing an extra object of the appropriate iterator categorytype so that the compiler will use overloading resolution to call theproper implementation: template doAdvance(iter, d,typename std::iterator_traits We can now summarize how to use a traits class: ■ // call the version// of doAdvance // that is // appropriate for// iter’s iterator// category Create a set of overloaded “worker” functions or function tem-plates (e.g., doAdvance) that differ in a traits parameter. Implementeach function in accord with the traits information passed.Create a “master” function or function template (e.g., advance) thatcalls the workers, passing information provided by a traits class. ■ Traits are widely used in the standard library. There’s iterator_traits, ofcourse, which, in addition to iterator_category, offers four other piecesof information about iterators (the most useful of which is value_type— Item42 shows an example of its use). There’s also char_traits, whichholds information about character types, and numeric_limits, whichserves up information about numeric types, e.g., their minimum andmaximum representable values, etc. (The name numeric_limits is a bitof a surprise, because the more common convention is for traitsclasses to end with “traits,” but numeric_limits is what it’s called, sonumeric_limits is the name we use.) TR1 (see Item54) introduces a slew of new traits classes that give infor-mation about types, including is_fundamental ✦ Traits classes make information about types available during com-pilation. They’re implemented using templates and template special-izations. In conjunction with overloading, traits classes make it possible toperform compile-time if...else tests on types. ✦ Index Operators are listed under operator. That is, operator<< is listed underoperator<<, not under <<, etc. Example classes, structs, and class or struct templates are indexedunder example classes/templates. Example function and functiontemplates are indexed under example functions/templates. Before A .NET7, 81, 135, 145, 194see also C# =, in initialization vs. assignment61066150 2nd edition of this book compared to 3rd editionxv–xvi, 277–279see also inside back cover3rd edition of this book compared to 2nd editionxv–xvi, 277–279see also inside back cover80-20 rule139, 168 alternatives to virtual functions169–177ambiguity multiple inheritance and192 nested dependent names and types205Arbiter, Petroniusvii argument-dependent lookup110 arithmetic, mixed-mode103, 222–226array layout, vs. object layout73array new254–255 array, invalid index and7 ASPECT_RATIO13 assignment see also operator= chaining assignments52copy-and-swap and56generalized220 to self, operator= and53–57vs. initialization6, 27–29, 114assignment operator, copy5auto_ptr, see std::auto_ptr automatically generated functions34–37copy constructor and copy assignment operator221disallowing37–39 avoiding code duplication50, 60 A Abrahams, Davidxvii, xviii, xixabstract classes43accessibility control over data members’95 name, multiple inheritance and193accessing names, in templatized bases207–212addresses inline functions136objects118 aggregation, see compositionAlexandrescu, Andreixixaliasing54 alignment249–250 allocators, in the STL240 B Bai, Yunxix Barry, Dave, allusion to229Bartolucci, Guidoxix Effective C++ base classescopying59 duplication of data in193lookup in, this-> and210 names hidden in derived classes263polymorphic44 polymorphic, destructors and40–44templatized207–212virtual193 basic guarantee, the128Battle of Hastings150Berck, Benjaminxix bidirectional iterators227 bidirectional_iterator_tag228 binary upgradeability, inlining and138binding dynamic, see dynamic bindingstatic, see static bindingbirds and penguins151–153 bitwise const member functions21–22books C++ Programming Language, ThexviiC++ TemplatesxviiiDesign Patternsxvii Effective STL273, 275–276Exceptional C++xvii Exceptional C++ Stylexvii, xviiiMore Effective C++273, 273–274More Exceptional C++xviiSatyriconvii Some Must Watch While Some Must Sleep150 Boost10, 269–272containers271 Conversion library270 correctness and testing support272data structures272 function objects and higher-order pro-gramming utilities271functionality not provided272 generic programming support271Graph library270 inter-language support272Lambda library271 math and numerics utilities271memory management utilities272MPL library270, 271 noncopyable base class39Pool library250, 251 scoped_array65, 216, 272shared_array65 shared_ptr implementation, costs83 smart pointers65, 272web pagexvii string and text utilities271template metaprogramming support271 Index 281 TR1 and9–10, 268, 269typelist support271web site10, 269, 272 boost, as synonym for std::tr1268Bosch, Derekxviii breakpoints, and inlining139Buffy the Vampire Slayerxxbugs, reportingxvibuilt-in types26–27 efficiency and passing89incompatibilities with80 C C standard library and C++ standard library264 C#43, 76, 97, 100, 116, 118, 190see also .NET C++ Programming Language, ThexviiC++ standard library263–269 array replacements and75C standard library and264C89 standard library and264header organization of101list template186logic_error and113set template185vector template75C++ Templatesxviii C++, as language federation11–13C++0x264 C++-style casts117 C, as sublanguage of C++12 C99 standard library, TR1 and267caching const and22mutable and22Cai, Stevexixcalling swap110 calls to base classes, casting and119Cargill, TomxviiiCarrara, EnricoxixCarroll, Glennxviiicasting116–123 see also const_castdynamic_cast, static_cast, , and reinterpret_castbase class calls and119constness away24–25encapsulation and123grep and117 syntactic forms116–117type systems and116 undefined behavior and119chaining assignments52 282IndexChang, BrandonxixClamage, Stevexviiiclass definitions artificial client dependencies, eliminating143 class declarations vs.143object sizes and141 class design, see type design class names, explicitly specifying162class, vs. typename203classes see also class definitions, interfacesabstract43, 162base see also base classes duplication of data in193polymorphic44 templatized207–212virtual193defining4derived see also inheritance virtual base initialization of194Handle144–145Interface145–147 meaning of no virtual functions41RAII, see RAII specification, see interfacestraits226–232client7 clustering objects251code bloat24, 135, 230 avoiding, in templates212–217copy assignment operator60duplication, see duplicationexception-safe127–134 factoring out of templates212–217incorrect, efficiency and90reuse195 sharing, see duplication, avoidingCohen, JakexixComeau, Gregxviii URL for his C/C++ FAQxviii common features and inheritance164commonality and variability analysis212compatibility, vptrs and42 compatible types, accepting218–222compilation dependencies140–148minimizing140–148, 190 pointers, references, and objects and143 compiler warnings262–263calls to virtuals and50inlining and136 partial copies and58 Effective C++ compiler-generated functions34–37disallowing37–39 functions compilers may generate221compilers parsing nested dependent names204programs executing within, see tem-plate metaprogrammingregister usage and89reordering operations76typename and207 when errors are diagnosed212compile-time polymorphism201composition184–186meanings of184 replacing private inheritance with189synonyms for184 vs. private inheritance188 conceptual constness, see const, logicalconsistency with the built-in types19, 86 const13, 17–26 bitwise21–22caching and22 casting away24–25 function declarations and18logical22–23 member functions19–25duplication and23–25 members, initialization of29overloading on19–20 pass by reference and86–90passing std::auto_ptr and220pointers17 return value18uses17 vs. #define13–14 const_cast25, 117 see also casting const_iterator, vs. iterators18constants, see const constraints on interfaces, from inheritance85constructors84copy5default4 empty, illusion of137 explicit5, 85, 104 implicitly generated34inlining and137–138operator new and137 possible implementation in derived classes138 relationship to new73static functions and52virtual146, 147 virtual functions and48–52 with vs. without arguments114containers, in Boost271 Effective C++ containment, see compositioncontinue, delete and62 control over data members’ accessibility95 convenience functions100 Conversion library, in Boost270 conversions, type, see type conversionscopies, partial58 copy assignment operator5 code in copy constructor and60derived classes and60copy constructors default definition35derived classes and60generalized219how used5 implicitly generated34pass-by-value and6copy-and-swap131assignment and56 exception-safe code and132copying base class parts59 behavior, resource management and66–69functions, the57objects57–60correctness designing interfaces for78–83testing and, Boost support272corresponding forms of newdelete and 73–75 corrupt data structures, exception-safe code and127 cows, coming home139 crimes against English39, 204cross-DLL problem82CRTP246 C-style casts116ctor8 curiously recurring template pattern246 D dangling handles126Dashtinezhad, Sasanxixdata members adding, copying functions and58control over accessibility95protected97 static, initialization of242why private94–98data structures exception-safe code and127in Boost272Davis, Tonyxviii Index283 deadly MI diamond193debuggers #define and13 inline functions and139declarations3 inline functions135 replacing definitions143 static const integral members14default constructors4 construction with arguments vs.114implicitly generated34default implementations for virtual functions, danger of163–167of copy constructor35of operator=35 default initialization, unintended59default parameters180–183impact if changed183static binding of182 #define debuggers and13 disadvantages of13, 16vs. const13–14 vs. inline functions16–17definitions4classes4 deliberate omission of38functions4 implicitly generated functions35objects4 pure virtual functions162, 166–167replacing with declarations143static class members242 static const integral members14templates4 variable, postponing113–116 delete see also operator deleteforms of73–75 operator delete and73 relationship to destructors73usage problem scenarios62 delete [], std::auto_ptr and tr1::shared_ptr and65deleters std::auto_ptr and68 tr1::shared_ptr and68, 81–83Delphi97 Dement, William150 dependencies, compilation140–148dependent names204 dereferencing a null pointer, undefined behavior of6derived classes copy assignment operators and60copy constructors and60 hiding names in base classes263 284Indeximplementing constructors in138virtual base initialization and194design contradiction in179of interfaces78–83of types78–86Design Patternsxviidesign patterns curiously recurring template (CRTP)246 encapsulation and173 generating from templates237Singleton31 Strategy171–177 Template Method170TMP and237destructors84 exceptions and44–48inlining and137–138pure virtual43 relationship to delete73 resource managing objects and63static functions and52virtual operatordelete and255 polymorphic base classes and40–44virtual functions and48–52Dewhurst, Stevexvii dimensional unit correctness, TMP and236 DLLs, delete and82dtor8 Dulimov, Peterxixduplication avoiding23–25, 29, 50, 60, 164, 183, 212– 217 base class data and193init function and60dynamic bindingdefinition of181 of virtual functions179 dynamic type, definition of181 dynamic_cast50, 117, 120–123 see also castingefficiency of120 E early binding180 easy to use correctly and hard to use incorrectly78–83 EBO, see empty base optimization Effective C++, compared to More Effective C++ and Effective STL273Effective STL273, 275–276 compared to Effective C++273 Effective C++ contents of275–276efficiency assignment vs. construction and destruction94 default parameter binding182 dynamic_cast120 Handle classes147 incorrect code and90, 94 init. with vs. without args114Interface classes147 macros vs. inline functions16member init. vs. assignment28minimizing compilation operator newdependencies147 /operator delete and248pass-by-reference and87pass-by-value and86–87 passing built-in types and89 runtime vs. compile-time tests230template metaprogramming and233template vs. function parameters216unused objects113virtual functions168Eiffel100 embedding, see composition empty base optimization (EBO)190–191encapsulation95, 99casts and123 design patterns and173handles and125measuring99 protected members and97RAII classes and72enum hack15–16, 236 errata list, for this bookxvierrors detected during linking39, 44runtime152 evaluation order, of parameters76example classes/templates A4 ABEntry27 AccessLevels95Address184 Airplane164, 165, 166Airport164 AtomicClock40AWOV43B4, 178, 262 Base54, 118, 137, 157, 158, 159, 160, 254, 255, 259 BelowBottom219 bidirectional_iterator_tag228Bird151, 152, 153Bitmap54 BorrowableItem192Bottom218 BuyTransaction49, 51 Effective C++ C5 Circle181 CompanyA208CompanyB208CompanyZ209CostEstimate15CPerson198 CTextBlock21, 22, 23Customer57, 58D178, 262 DatabaseID197Date58, 79Day79 DBConn45, 47DBConnection45deque229 deque::iterator229 Derived54, 118, 137, 157, 158, 159, 160, 206, 254, 260Directory31 ElectronicGadget192Ellipse161Empty34, 190 EvilBadGuy172, 174EyeCandyCharacter175Factorial235 Factorial<0>235File193, 194FileSystem30FlyingBird152Font71 forward_iterator_tag228 GameCharacter169, 170, 172, 173, 176GameLevel174GamePlayer14, 15GraphNode4GUIObject126 HealthCalcFunc176HealthCalculator174HoldsAnInt190, 191HomeForSale37, 38, 39input_iterator_tag228 input_iterator_tag see also std::iterator_traits list229 list::iterator229Lock66, 67, 68 LoggingMsgSender208, 210, 211Middle218 ModelA164, 165, 167ModelB164, 165, 167ModelC164, 166, 167Month79, 80MP3Player192 Index285 MsgInfo208MsgSender208 MsgSender Person86, 135, 140, 141, 142, 145, 146, 150, 184, 187PersonInfo195, 197PhoneNumber27, 184PMImpl131 Point26, 41, 123 PrettyMenu127, 130, 131PriorityCustomer58 random_access_iterator_tag228 Rational90, 102, 103, 105, 222, 223, 224, 225, 226 RealPerson147 Rectangle124, 125, 154, 161, 181, 183RectData124 SellTransaction49Set185 Shape161, 162, 163, 167, 180, 182, 183SmartPtr218, 219, 220SpecialString42 SpecialWindow119, 120, 121, 122SpeedDataCollection96Square154 SquareMatrix213, 214, 215, 216SquareMatrixBase214, 215StandardNewDeleteForms260Student86, 150, 187TextBlock20, 23, 24TimeKeeper40, 41Timer188Top218 Transaction48, 50, 51Uncopyable39WaterClock40 WebBrowser98, 100, 101 Widget4, 5, 44, 52, 53, 54, 56, 107, 108, 109, 118, 189, 199, 201, 242, 245, 246, 257, 258, 261 Widget::WidgetTimer189WidgetImpl106, 108 Window88, 119, 121, 122WindowWithScrollBars88WristWatch40X242Y242Year79 example functions/templates ABEntry::ABEntry27, 28 AccessLevels::getReadOnly95AccessLevels::getReadWrite95AccessLevels::setReadOnly95 286IndexAccessLevels::setWriteOnly95advance228, 230, 232, 233, 234Airplane::defaultFly165 Airplane::fly164, 165, 166, 167askUserForDatabaseID195AWOV::AWOV43B::mf178 Base::operator delete255Base::operator new254Bird::fly151 BorrowableItem::checkOut192boundingBox126 BuyTransaction::BuyTransaction51BuyTransaction::createLogString51calcHealth174callWithMax16changeFontSize71Circle::draw181 clearAppointments143, 144clearBrowser98 CPerson::birthDate198CPerson::CPerson198CPerson::name198 CPerson::valueDelimClose198CPerson::valueDelimOpen198 createInvestment62, 70, 81, 82, 83CTextBlock::length22, 23CTextBlock::operator[]21Customer::Customer58Customer::operator=58D::mf178Date::Date79Day::Day79daysHeld69 DBConn::~DBConn45, 46, 47DBConn::close47 defaultHealthCalc172, 173Derived::Derived138, 206Derived::mf1160Derived::mf4157 Directory::Directory31, 32doAdvance231doMultiply226 doProcessing200, 202 doSomething5, 44, 54, 110doSomeWork118eat151, 187 ElectronicGadget::checkOut192Empty::~Empty34Empty::Empty34Empty::operator=34 encryptPassword114, 115error152 EvilBadGuy::EvilBadGuy172f62, 63, 64 FlyingBird::fly152Font::~Font71Font::Font71Font::get71 Effective C++ Font::operator FontHandle71 GameCharacter::doHealthValue170 GameCharacter::GameCharacter172, 174, 176 GameCharacter::healthValue169, 170, 172, 174, 176 GameLevel::health174getFont70 hasAcceptableQuality6HealthCalcFunc::calc176 HealthCalculator::operator()174lock66 Lock::~Lock66Lock::Lock66, 68logCall57 LoggingMsgSender::sendClear208, 210, 211 loseHealthQuickly172loseHealthSlowly172main141, 142, 236, 241makeBigger154makePerson195max135 ModelA::fly165, 167ModelB::fly165, 167ModelC::fly166, 167Month::Dec80Month::Feb80Month::Jan80 Month::Month79, 80 MsgSender::sendClear208MsgSender::sendSecret208 MsgSender NewHandlerHolder::~NewHandlerHolder243NewHandlerHolder::NewHandlerHolder243NewHandlerSupport::operator new245NewHandlerSupport::set_new_handler245 numDigits4 operator delete255operator new249, 252 operator*91, 92, 94, 105, 222, 224, 225, 226 operator==93outOfMem240Penguin::fly152Person::age135 Person::create146, 147Person::name145Person::Person145 PersonInfo::theName196 PersonInfo::valueDelimClose196PersonInfo::valueDelimOpen196 PrettyMenu::changeBackground127, 128, 130, 131 print20 print2nd204, 205 printNameAndDisplay88, 89priority75 PriorityCustomer::operator=59 Effective C++ PriorityCustomer::PriorityCustomer59processWidget75 RealPerson::~RealPerson147RealPerson::RealPerson147Rectangle::doDraw183Rectangle::draw181, 183 Rectangle::lowerRight124, 125Rectangle::upperLeft124, 125releaseFont70Set::insert186Set::member186Set::remove186Set::size186 Shape::doDraw183 Shape::draw161, 162, 180, 182, 183Shape::error161, 163Shape::objectID161, 167SmartPtr::get220 SmartPtr::SmartPtr220someFunc132, 156 SpecialWindow::blink122 SpecialWindow::onResize119, 120SquareMatrix::invert214 SquareMatrix::setDataPtr215 SquareMatrix::SquareMatrix215, 216StandardNewDeleteForms::operator delete260, 261 StandardNewDeleteForms::operator new260, 261std::swap109 std::swap TextBlock::operator[]20, 23, 24tfs32 Timer::onTick188Transaction::init50 Transaction::Transaction49, 50, 51Uncopyable::operator=39Uncopyable::Uncopyable39unlock66 validateStudent87Widget::onTick189 Widget::operator new244Widget::operator+=53 Widget::operator=53, 54, 55, 56, 107Widget::set_new_handler243Widget::swap108Window::blink122Window::onResize119workWithIterator206, 207Year::Year79 exception specifications85Exceptional C++xvii Exceptional C++ Stylexvii, xviiiexceptions113delete and62 Index287 destructors and44–48member swap and112 standard hierarchy for264swallowing46 unused objects and114exception-safe code127–134copy-and-swap and132legacy code and133pimpl idiom and131side effects and132 exception-safety guarantees128–129 explicit calls to base class functions211explicit constructors5, 85, 104 generalized copy construction and219explicit inline request135 explicit specification, of class names162explicit type conversions vs. implicit70– 72 expression templates237 expressions, implicit interfaces and201 F factoring code, out of templates212–217factory function40, 62, 69, 81, 146, 195Fallenstedt, Martinxix federation, of languages, C++ as11–13Fehér, Attila F.xix final classes, in Java43final methods, in Java190 fixed-size static buffers, problems of196forms of new and delete73–75FORTRAN42 forward iterators227 forward_iterator_tag228 forwarding functions144, 160French, Donaldxx friend functions38, 85, 105, 135, 173, 223– 225 vs. member functions98–102friendship in real life105 without needing special access rights225 Fruchterman, Thomasxix FUDGE_FACTOR15 Fuller, Johnxx function declarations, const in18function objectsdefinition of6 higher-order programming utilities and, in Boost271 functions convenience100copying57 288Indexdefining4 deliberately not defining38factory, see factory functionforwarding144, 160 implicitly generated34–37, 221disallowing37–39inline, declaring135member templatized218–222 vs. non-member104–105non-member templates and222–226 type conversions and102–105, 222– 226 non-member non-friend, vs member98–102 non-virtual, meaning168return values, modifying21 signatures, explicit interfaces and201static ctors and dtors and52virtual, see virtual functionsfunction-style casts116 G Gamma, ErichxviiGeller, Alanxix generalized assignment220 generalized copy constructors219generative programming237 generic programming support, in Boost271 get, smart pointers and70 goddess, see Urbano, Nancy L.goto,delete and62 Graph library, in Boost270grep, casts and117 guarantees, exception safety128–129Gutnik, Genexix H Handle classes144–145handles125dangling126 encapsulation and125operator[] and126returning123–126has-a relationship184hash tables, in TR1266Hastings, Battle of150Haugland, Solveigxx head scratching, avoiding95header files, see headers Effective C++ headers for declarations vs. for definitions144inline functions and135namespaces and100 of C++ standard library101templates and136usage, in this book3 hello world, template metaprogramming and235 Helm, RichardxviiHenney, KevlinxixHicks, Coryxix hiding names, see name hiding higher-order programming and function object utilities, in Boost271highlighting, in this book5 I identity test55 if...else for types230 #ifdef17#ifndef17 implementation-dependent behavior, warnings and263implementations decoupling from interfaces165default, danger of163–167inheritance of161–169 of derived class constructors and destructors137of Interface classes147references89 std::max135std::swap106 implicit inline request135implicit interfaces199–203 implicit type conversions vs. explicit70– 72 implicitly generated functions34–37, 221disallowing37–39#include directives17 compilation dependencies and140incompatibilities, with built-in types80incorrect code and efficiency90infinite loop, in operatornew253inheritance accidental165–166 combining with templates243–245common features and164intuition and151–155mathematics and155mixin-style244 name hiding and156–161of implementation161–169of interface161–169 Effective C++ of interface vs. implementation161–169operator new and253–254 penguins and birds and151–153private187–192protected151public150–155 rectangles and squares and153–155redefining non-virtual functions and178–180scopes and156 sharing features and164inheritance, multiple192–198ambiguity and192 combining public and private197deadly diamond193inheritance, private214 combining with public197eliminating189 for redefining virtual functions197meaning187 vs. composition188inheritance, public combining with private197is-a relationship and150–155meaning of150 name hiding and159 virtual inheritance and194inheritance, virtual194init function60 initialization4, 26–27assignment vs.6built-in types26–27const members29 const static members14default, unintended59 in-class, of static const integral members14 local static objects31 non-local static objects30objects26–33 reference members29static members242 virtual base classes and194vs. assignment27–29, 114 with vs. without arguments114initialization orderclass members29importance of31 non-local statics29–33inline functionssee also inliningaddress of136 as request to compiler135debuggers and139declaring135headers and135 optimizing compilers and134recursion and136vs. #define16–17 Index289 vs. macros, efficiency and16inlining134–139 constructors/destructors and137–138dynamic linking and139Handle classes and148inheritance and137–138Interface classes and148library design and138recompiling and139relinking and139 suggested strategy for139templates and136time of135 virtual functions and136input iterators227 input_iterator_tag228 input_iterator_tag insomnia150 instructions, reordering by compilers76integral types14 Interface classes145–147interfaces decoupling from implementations165definition of7 design considerations78–86explicit, signatures and201implicit199–203 expressions and201inheritance of161–169new types and79–80 separating from implementations140template parameters and199–203undeclared85 inter-language support, in Boost272internationalization, library support for264 invalid array index, undefined behavior and7invariants NVI and171 over specialization168 is-a relationship150–155 is-implemented-in-terms-of184–186, 187istream_iterators227 iterator categories227–228 iterator_category229 iterators as handles125 iterators, vs. const_iterators18 J Jagdhar, EmilyxixJanert, Philippxix Java7, 43, 76, 81, 100, 116, 118, 142, 145, 190, 194 290IndexJohnson, RalphxviiJohnson, Timxviii, xixJosuttis, Nicolai M.xviii K Kaelbling, Mikexviii Kakulapati, GunavardhanxixKalenkovich, EugenexixKennedy, Glennxix Kernighan, Brianxviii, xixKimura, JunichixviiiKirman, JakxviiiKirmse, AndrewxixKnox, Timothyxviii, xixKoenig lookup110 Kourounis, DrososxixKreuzer, Gerhardxix L Laeuchli, Jessexix Lambda library, in Boost271Langer, Angelikaxix languages, other, compatibility with42Lanzetta, Michaelxixlate binding180 layering, see compositionlayouts, objects vs. arrays73Lea, Dougxviii leaks, exception-safe code and127Leary-Coutu, ChandaxxLee, Samxix legacy code, exception-safety and133Lejter, Moisesxviii, xxlemur, ring-tailed196Lewandowski, Scottxviiilhs, as parameter name8Li, Gregxix link-time errors39, 44link-time inlining135 list186 local static objectsdefinition of30initialization of31locales264 locks, RAII and66–68logic_error class113 logically const member functions22–23 M mailing list for Scott Meyersxvi Effective C++ maintenance common base classes and164delete and62 managing resources, see resource man-agement Manis, VincentxixMarin, Alexxix math and numerics utilities, in Boost271mathematical functions, in TR1267mathematics, inheritance and155matrix operations, optimizing237Matthews, Leonxix max, std, implementation of135Meadowbrooke, Chrystaxixmeaning of classes without virtual functions41of composition184 of non-virtual functions168of pass-by-value6 of private inheritance187of public inheritance150 of pure virtual functions162of references91 of simple virtual functions163measuring encapsulation99Meehan, Jimxix member data, see data membersmember function templates218–222member functionsbitwise const21–22 common design errors168–169 const19–25 duplication and23–25encapsulation and99 implicitly generated34–37, 221disallowing37–39logically const22–23private38 protected166 vs. non-member functions104–105vs. non-member non-friends98–102member initialization for const static integral members14lists28–29 vs. assignment28–29order29 memory allocationarrays and254–255 error handling for240–246 memory leaks, new expressions and256memory management functions, replacing247–252multithreading and239, 253utilities, in Boost272 metaprogramming, see template metapro-gramming Effective C++ Meyers, Scott mailing list forxviweb site forxvimf, as identifier9Michaels, LauraxviiiMickelsen, Denisexxminimizing compilation dependencies140–148, 190Mittal, Nishantxix mixed-mode arithmetic103, 104, 222–226mixin-style inheritance244 modeling is-implemented-in-terms-of184–186 modifying function return values21Monty Python, allusion to91Moore, Vanessaxx More Effective C++273, 273–274compared to Effective C++273contents of273–274More Exceptional C++xviiMoroff, Halxix MPL library, in Boost270, 271 multiparadigm programming language, C++ as11 multiple inheritance, see inheritancemultithreading memory management routines and239, 253 non-const static objects and32treatment in this book9 mutable22–23 mutexes, RAII and66–68 N Nagler, EricxixNahil, Juliexxname hiding inheritance and156–161 operators new/delete and259–261using declarations and159name lookupthis-> and210 using declarations and211 name shadowing, see name hidingnames accessing in templatized bases207–212available in both C and C++3dependent204 hidden by derived classes263nested, dependent204non-dependent204namespaces110headers and100 namespace pollution in a class166Nancy, see Urbano, Nancy L. Index291 Nauroth, Chrisxix nested dependent names204 nested dependent type names, typename and205 new see also operator new expressions, memory leaks and256forms of73–75 operator new and73 relationship to constructors73smart pointers and75–77 new types, interface design and79–80new-handler240–247definition of240deinstalling241identifying253 new-handling functions, behavior of241new-style casts117 noncopyable base class, in Boost39non-dependent names204 non-local static objects, initialization of30 non-member functions member functions vs.104–105templates and222–226 type conversions and102–105, 222–226non-member non-friend functions98–102non-type parameters213non-virtual functions178–180 static binding of178interface idiom, see NVInothrow guarantee, the129nothrow new246null pointerdeleting255dereferencing6 set_new_handler and241NVI170–171, 183 O object-oriented C++, as sublanguage of C++12 object-oriented principles, encapsulation and99objects alignment of249–250clustering251 compilation dependencies and143copying all parts57–60defining4 definitions, postponing113–116handles to internals of123–126initialization, with vs. without arguments114 layout vs. array layout73 292Indexmultiple addresses for118partial copies of58 placing in shared memory251resource management and61–66returning, vs. references90–94size, pass-by-value and89sizes, determining141vs. variables3 Oldham, Jeffrey D.xixold-style casts117 operations, reordering by compilers76 operatordelete84see also delete behavior of255efficiency of248 name hiding and259–261 non-member, pseudocode for255placement256–261replacing247–252 standard forms of260 virtual destructors and255 operatordelete[]84, 255operatornew84see also new arrays and254–255bad_alloc and246, 252behavior of252–255efficiency of248 infinite loop within253inheritance and253–254 member, and “wrongly sized” requests254 name hiding and259–261 new-handling functions and241non-member, pseudocode for252 out-of-memory conditions and240–241,252–253 placement256–261replacing247–252returning 0 and246standard forms of260 std::bad_alloc and246, 252operatornew[]84, 254–255 operator() (function call operator)6operator= const members and36–37 default implementation35implicit generation34 reference members and36–37return value of52–53 self-assignment and53–57 when not implicitly generated36–37 operator[]126 overloading on const19–20return type of21optimization by compilers94 Effective C++ during compilation134inline functions and134order initialization of non-local statics29–33member initialization29ostream_iterators227 other languages, compatibility with42output iterators227 output_iterator_tag228 overloading as if...else for types230onconst19–20 std::swap109 overrides of virtuals, preventing189ownership transfer68 P Pal, Balogxixparameters see also pass-by-value, pass-by-refer-ence default180–183 evaluation order76 non-type, for templates213 type conversions and, see type conver-sions Pareto Principle, see 80-20 rule parsing problems, nested dependent names and204partial copies58 partial specialization function templates109 std::swap108 parts, of objects, copying all57–60pass-by-reference, efficiency and87pass-by-reference-to-const, vs pass-by-value86–90pass-by-value copy constructor and6efficiency of86–87meaning of6 object size and89 vs. pass-by-reference-to-const86–90patterns see design patternsPedersen, Roger E.xix penguins and birds151–153performance, see efficiencyPersephoneix, xx, 36pessimization93 physical constness, see const, bitwisepimpl idiom definition of106 exception-safe code and131 Effective C++ placement delete, see operator deleteplacement new, see operator newPlato87 pointer arithmetic and undefined behavior119pointers see also smart pointersas handles125 bitwise const member functions and21compilation dependencies and143 const17 in headers14 null, dereferencing6 template parameters and217 to single vs. multiple objects, and delete73 polymorphic base classes, destructors and40–44 polymorphism199–201compile-time201runtime200 Pool library, in Boost250, 251 postponing variable definitions113–116Prasertsith, Chutixx preconditions, NVI and171 pregnancy, exception-safe code and133private data members, why94–98private inheritance, see inheritanceprivate member functions38private virtual functions171properties97protected data members97 inheritance, see inheritancemember functions166 members, encapsulation of97public inheritance, see inheritancepun, really bad152 pure virtual destructorsdefining43 implementing43 pure virtual functions43defining162, 166–167meaning162 R Rabbani, DannyxixRabinowitz, MartyxxRAII63, 70, 243classes72 copying behavior and66–69encapsulation and72mutexes and66–68 random access iterators227 Index293 random number generation, in TR1267 random_access_iterator_tag228 RCSP, see smart pointers reading uninitialized values26rectangles and squares153–155 recursive functions, inlining and136redefining inherited non-virtual functions178–180Reed, KathyxxReeves, Jackxixreferences as handles125 compilation dependencies and143functions returning31implementation89meaning91 members, initialization of29returning90–94 to static object, as function return value92–94 register usage, objects and89regular expressions, in TR1266 reinterpret_cast117, 249 see also castingrelationshipshas-a184is-a150–155 is-implemented-in-terms-of184–186, 187 reordering operations, by compilers76replacing definitions with declarations143 replacing new/delete247–252replication, see duplication reporting, bugs in this bookxvi Resource Acquisition Is Initialization, see RAII resource leaks, exception-safe code and127 resource managementsee also RAII copying behavior and66–69objects and61–66 raw resource access and69–73 resources, managing objects and69–73return by reference90–94return types const18 objects vs. references90–94of operator[]21 return value of operator=52–53returning handles123–126reuse, see code reuse revenge, compilers taking58rhs, as parameter name8 294IndexRoze, Mikexix rule of 80-20139, 168runtime errors152inlining135 polymorphism200 S Saks, Danxviii Santos, Eugene, Jr.xviiiSatch36Satyriconvii Scherpelz, JeffxixSchirripa, Stevexix Schober, Hendrikxviii, xixSchroeder, Sandraxx scoped_array65, 216, 272 scopes, inheritance and156sealed classes, in C#43sealed methods, in C#190 second edition, see 2nd edition self-assignment, operator= and53–57 set185 set_new_handler class-specific, implementing243–245using240–246 set_unexpected function129 shadowing, names, see name shadowingShakespeare, William156 shared memory, placing objects in251 shared_array65 shared_ptr implementation in Boost, costs83 sharing code, see duplication, avoidingsharing common features164Shewchuk, Johnxviii side effects, exception safety and132signatures definition of3 explicit interfaces and201 simple virtual functions, meaning of163Singh, SiddharthaxixSingleton pattern31 size_t3 sizeof253, 254 empty classes and190 freestanding classes and254sizes of freestanding classes254of objects141sleeping pills150 slist227 Smallberg, Davidxviii, xix Effective C++ Smalltalk142 smart pointers63, 64, 70, 81, 121, 146, 237see also std::auto_ptrget and tr1::shared_ptr and70 in Boost65, 272web page forxviiin TR1265 newed objects and75–77 type conversions and218–220Socrates87 Some Must Watch While Some Must Sleep150Somers, Jeffxixspecialization invariants over168 partial, of std::swap108total, of std::swap107, 108specification, see interfaces squares and rectangles153–155standard exception hierarchy264 standard forms of operator new/delete260standard library, see C++ standard library, C standard librarystandard template library, see STLStasko, Johnxviii statements using new, smart pointers and75–77static binding of default parameters182of non-virtual functions178 objects, returning references to92–94type, definition of180 static functions, ctors and dtors and52static members const member functions and21definition242initialization242static objects definition of30 multithreading and32 static_cast25, 82, 117, 119, 249 see also casting std namespace, specializing templates in107 std::auto_ptr63–65, 70 conversion to tr1::shared_ptrdelete [] and220 and65 pass by const and220 std::auto_ptr, deleter support and68std::char_traits232 std::iterator_traits, pointers and230std::list186 std::max, implementation of135std::numeric_limits232 Effective C++ std::set185std::size_t3std::swap see also swap implementation of106overloading109 partial specialization of108total specialization of107, 108std::tr1, see TR1 stepping through functions, inlining and139STL allocators240 as sublanguage of C++12containers, swap and108definition of6 iterator categories in227–228Strategy pattern171–177 string and text utilities, in Boost271strong guarantee, the128Stroustrup, Bjarnexvii, xviiiStroustrup, NicholasxixSutter, Herbxvii, xviii, xixswallowing exceptions46 swap106–112 see also std::swap calling110 exceptions and112 STL containers and108when to write111 symbols, available in both C and C++3 T template C++, as sublanguage of C++12template metaprogramming233–238efficiency and233hello world in235 pattern implementations and237support in Boost271support in TR1267 Template Method pattern170templates code bloat, avoiding in212–217 combining with inheritance243–245defining4 errors, when detected212expression237headers and136 in std, specializing107inlining and136instantiation of222 member functions218–222 names in base classes and207–212non-type parameters213parameters, omitting224 Index295 pointer type parameters and217shorthand for224 specializations229, 235partial109, 230total107, 209 type conversions and222–226type deduction for223 temporary objects, eliminated by compilers94 terminology, used in this book3–8 testing and correctness, Boost support for272 text and string utilities, in Boost271third edition, see 3rd edition this->, to force base class lookup210threading, see multithreadingTilly, Barbaraxviii TMP, see template metaprogrammingTondo, ClovisxviiiTopic, Michaelxix total class template specialization209total specialization of std::swap107, 108total template specializations107TR19, 264–267 array component267bind component266 Boost and9–10, 268, 269 boost as synonym for std::tr1268C99 compatibility component267function component265 hash tables component266 math functions component267mem_fn component267 random numbers component267reference_wrapper component267regular expression component266result_of component267 smart pointers component265support for TMP267tuples component266 type traits component267URL for information on268 tr1::array267 tr1::bind175, 266 tr1::function173–175, 265tr1::mem_fn267 tr1::reference_wrapper267tr1::result_of267 tr1::shared_ptr53, 64–65, 70, 75–77 construction from other smart pointers and220 cross-DLL problem and82delete [] and65 deleter support in68, 81–83 member template ctors in220–221 tr1::tuple266 296Indextr1::unordered_map43, 266tr1::unordered_multimap266tr1::unordered_multiset266tr1::unordered_set266tr1::weak_ptr265 traits classes226–232transfer, ownership68 translation unit, definition of30Trux, AntoinexviiiTsao, Mikexix tuples, in TR1266 type conversions85, 104explicit ctors and5implicit104 implicit vs. explicit70–72 non-member functions and102–105, 222–226 private inheritance and187smart pointers and218–220templates and222–226 type deduction, for templates223type design78–86 type traits, in TR1267 typedef, typename and206–207typedefs, new/delete and75 typeid50, 230, 234, 235 typelists271 typename203–207 compiler variations and207typedef and206–207vs. class203types built-in, initialization26–27 compatible, accepting all218–222if...else for230 integral, definition of14traits classes and226–232 U undeclared interface85undefined behavioradvance and231 array deletion and73 casting + pointer arithmetic and119definition of6 destroyed objects and91exceptions and45 initialization order and30invalid array index and7multiple deletes and63, 247null pointers and6 object deletion and41, 43, 74uninitialized values and26 undefined values of members before con-struction and after destruction50 Effective C++ unexpected function129 uninitialized data members, virtual functions and49values, reading26 unnecessary objects, avoiding115unused objectscost of113 exceptions and114 Urbano, Nancy L.vii, xviii, xxsee also goddessURLs Boost10, 269, 272 Boost smart pointersxviiEffective C++ errata listxvi Effective C++ TR1 Info. Page268Greg Comeau’s C/C++ FAQxviiiScott Meyers’ mailing listxviScott Meyers’ web sitexvithis book’s errata listxvi usage statistics, memory management and248 using declarations name hiding and159name lookup and211 V valarray264 value, pass by, see pass-by-valueVan Wyk, Chrisxviii, xixVandevoorde, Davidxviiivariable, vs. object3 variables definitions, postponing113–116vector template75Viciana, Pacoxix virtual base classes193 virtual constructors146, 147virtual destructors operator delete and255 polymorphic base classes and40–44virtual functions alternatives to169–177ctors/dtors and48–52 default implementations and163–167default parameters and180–183dynamic binding of179efficiency and168 explict base class qualification and211implementation42inlining and136 language interoperability and42meaning of none in class41preventing overrides189private171 pure, see pure virtual functionssimple, meaning of163 Effective C++ uninitialized data members and49virtual inheritance, see inheritancevirtual table42 virtual table pointer42Vlissides, Johnxvii Index297 vptr42vtbl42 W Wait, Johnxx warnings, from compiler262–263calls to virtuals and50inlining and136 partial copies and58web sites, see URLs Widget class, as used in this book8Wiegers, KarlxixWilson, Matthewxix Wizard of Oz, allusion to154 X XP, allusion to225XYZ Airlines163 Z Zabluda, OlegxviiiZolman, Leorxviii, xix 因篇幅问题不能全部显示,请点此查看更多更全内容