您的当前位置:首页正文

Effective C++

2022-08-07 来源:客趣旅游网
Praise for Effective C++, Third Edition

“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;

templateclass GraphNode;

// 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();...};

templateclass GraphNode {public:

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::iterator, set::iterator, etc.), algorithms (e.g.,for_each, find, sort, etc.), and related functionality. Much of that relatedfunctionality has to do with function objects: objects that act likefunctions. Such objects come from classes that overload operator(), thefunction call operator. If you’re unfamiliar with the STL, you’ll want tohave a decent reference available as you read this book, because theSTL is too useful for me not to take advantage of it. Once you’ve usedit a little, you’ll feel the same way.

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(expression)dynamic_cast(expression)reinterpret_cast(expression)static_cast(expression)

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(15));

// 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(x)/y;

// 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(*this).onResize();

...

// 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 > VPW; // on tr1::shared_ptrVPW winPtrs;...

for (VPW::iterator iter = winPtrs.begin();// undesirable code:

iter != winPtrs.end();// uses dynamic_cast++iter) {

if (SpecialWindow *psw = dynamic_cast(iter->get()))psw->blink();}

try to do this instead:

typedef std::vector > VPSW;VPSW winPtrs;...

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 > VPW;VPW winPtrs;// container holds

// (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 > VPW;VPW winPtrs;...

for (VPW::iterator iter = winPtrs.begin(); iter != winPtrs.end(); ++iter){

if (SpecialWindow1 *psw1 =

dynamic_cast(iter->get())) { ... }else if (SpecialWindow2 *psw2 =

dynamic_cast(iter->get())) { ... }

else if (SpecialWindow3 *psw3 =

dynamic_cast(iter->get())) { ... }

...}

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 doMultiply(const Rational& lhs,

const Rational& rhs);

templateclass Rational {public:...friend

const Rational operator*(const Rational& lhs,

const Rational& rhs)

{ 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// defineconst Rational doMultiply(const Rational& lhs,// helper

const Rational& rhs)// template in

{// header file,return Rational(lhs.numerator() * rhs.numerator(),// if necessary

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

templatevoid advance(IterT& iter, DistT d);

// 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:

templatevoid advance(IterT& iter, DistT d){

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:

templatestruct iterator_traits; // template for information about// iterator types

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. Thistypedef identifies the iterator category of IterT.

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”templatestruct iterator_traits {

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// partial template specializationstruct iterator_traits// for built-in pointer types{

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:

templatevoid advance(IterT& iter, DistT d){

if (typeid(typename std::iterator_traits::iterator_category) ==typeid(std::random_access_iterator_tag))...}

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::iterator_category canalso be determined during compilation. Yet the if statement is evalu-ated at runtime (unless your optimizer is crafty enough to get rid of it).Why do something at runtime that we can do during compilation? Itwastes time (literally), and it bloats our executable.

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:

templatevoid doAdvance(IterT& iter, DistT d,

std::random_access_iterator_tag)

{

iter += d;}

templatevoid doAdvance(IterT& iter, DistT d,

std::bidirectional_iterator_tag)

{

if (d >= 0) { while (d--) ++iter; }else { while (d++) --iter; }}

templatevoid doAdvance(IterT& iter, DistT d,

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:

templatevoid advance(IterT& iter, DistT d){

doAdvance(iter, d,typename

std::iterator_traits::iterator_category());}

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 (whether T is a built-intype), is_array (whether T is an array type), and is_base_of(whether T1 is the same as or is a base class of T2). All told, TR1 addsover 50 traits classes to standard C++.Things to Remember

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 and144

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_tag230InputFile193, 194Investment61, 70IOFile193, 194IPerson195, 197iterator_traits229

see also std::iterator_traits

list229

list::iterator229Lock66, 67, 68

LoggingMsgSender208, 210, 211Middle218

ModelA164, 165, 167ModelB164, 165, 167ModelC164, 166, 167Month79, 80MP3Player192

Index285

MsgInfo208MsgSender208

MsgSender209NamedObject35, 36NewHandlerHolder243NewHandlerSupport245output_iterator_tag228OutputFile193, 194Penguin151, 152, 153

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::sendSecret209

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::swap107, 108study151, 187swap106, 109tempDir32

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_tag230

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 specialization168144

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

因篇幅问题不能全部显示,请点此查看更多更全内容