(This page has no text content)
100 C++ Mistakes and How to Avoid Them Rich Yonts To comment go to liveBook Manning Shelter Island For more information on this and other Manning titles go to www.manning.com
Copyright For online information and ordering of this and other Manning books, please visit www.manning.com. The publisher offers discounts on these books when ordered in quantity. For more information, please contact Special Sales Department Manning Publications Co. 20 Baldwin Road PO Box 761 Shelter Island, NY 11964 Email: orders@manning.com ©2025 by Manning Publications Co. All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by means electronic, mechanical, photocopying, or otherwise, without prior written permission of the publisher. Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in the book, and Manning
Publications was aware of a trademark claim, the designations have been printed in initial caps or all caps. ♾ Recognizing the importance of preserving what has been written, it is Manning’s policy to have the books we publish printed on acid-free paper, and we exert our best efforts to that end. Recognizing also our responsibility to conserve the resources of our planet, Manning books are printed on paper that is at least 15 percent recycled and processed without the use of elemental chlorine. The author and publisher have made every effort to ensure that the information in this book was correct at press time. The author and publisher do not assume and hereby disclaim any liability to any party for any loss, damage, or disruption caused by errors or omissions, whether such errors or omissions result from negligence, accident, or any other cause, or from any usage of the information herein. Manning Publications Co. 20 Baldwin Road Technical PO Box 761 Shelter Island, NY 11964 Development editor: Doug Rudder Technical editor: Matt Godbolt Review editor: Radmila Ercegovac Production editor: Kathy Rossland Copy editor: Christian Berk Proofreader: Keri Hales
Technical proofreader: Abel Sen Typesetter: Tamara Švelić Sabljić Cover designer: Marija Tudor ISBN: 9781633436893
contents Front matter preface acknowledgments about this book about the author about the cover illustration 1 C++: With great power comes great responsibility 1.1 Mistakes A quick example 1.2 Anatomy of a mistake Correctness Readability Effectiveness Performance 1.3 Learning from our mistakes Noticing mistakes Understanding mistakes Fixing mistakes Learning from mistakes 1.4 Where we’ll find mistakes Class design Program implementation Library problems
Modern C++ Old standards and usage Lost expertise and misguided training 1.5 A word about organization Part 1. Modern C++ 2 Better modern C++: Classes and types 2.1 Mistake 1: Failing to use move semantics 2.2 Mistake 2: Using empty exception specifications 2.3 Mistake 3: Not using override on derived virtual functions 2.4 Mistake 4: Writing simple or hiding unwanted supplied class members 2.5 Mistake 5: Not using in-class initializers 2.6 Mistake 6: Overusing index-based loops 2.7 Mistake 7: Failing to use nullptr 2.8 Mistake 8: Not using unique_ptrs for exclusive ownership 2.9 Mistake 9: Not using shared_ptrs for shared ownership 3 Better modern C++: General programming 3.1 Mistake 10: Failing to use if with initialization 3.2 Mistake 11: Not using type inference for variables 3.3 Mistake 12: Using typedef
3.4 Mistake 13: Writing common algorithms 3.5 Mistake 14: Not using uniform initialization 3.6 Mistake 15: Failing to use emplacement 3.7 Mistake 16: Failing to use tuples 3.8 Mistake 17: Not using structured binding 4 Better modern C++: Additional topics 4.1 Mistake 18: Not using variadic templates 4.2 Mistake 19: Using global namespace enums 4.3 Mistake 20: Not using new formatting functionality 4.4 Mistake 21: Not using ranges with containers 4.5 Mistake 22: Writing nonportable filesystem code 4.6 Mistake 23: Writing excessive standalone functions 4.7 Mistake 24: Using awkward constants 4.8 Mistake 25: Writing pattern-matching code Part 2. Transitional C++ 5 C idioms 5.1 Mistake 26: Always declaring variables at the top of a function 5.2 Mistake 27: Depending on macros 5.3 Mistake 28: Misunderstanding NULL 5.4 Mistake 29: Accessing disk files using FILE
5.5 Mistake 30: Using integers for Boolean values 5.6 Mistake 31: Using C-style casts 5.7 Mistake 32: Converting text with atoi 5.8 Mistake 33: Using C-style strings 5.9 Mistake 34: Calling the exit function 5.10 Mistake 35: Preferring arrays to vectors 6 Better premodern C++ 6.1 Mistake 36: Input and output using scanf and printf 6.2 Mistake 37: Overusing endl 6.3 Mistake 38: Dynamic allocation with malloc and free 6.4 Mistake 39: Using unions for type conversion 6.5 Mistake 40: Using varargs for variable parameter lists 6.6 Mistake 41: Incorrect class initialization order 6.7 Mistake 42: Adding nonvalue types to containers 6.8 Mistake 43: Favoring indexes over iterators Part 3. Classic (premodern) C++ 7 Establishing the class invariant 7.1 Class invariants enforce proper class design Interpretation Set of operations
Range of values Memory mechanics Performance implications 7.2 Mistakes in class design The class invariant Establishing the class invariant 7.3 Mistake 44: Failing to maintain the class invariant 7.4 Mistake 45: Not thinking of classes as data types 7.5 Mistake 46: Not establishing a basis for methods 7.6 Mistake 47: Failing to code the big 3 7.7 Mistake 48: Using inheritance just for code reuse 7.8 Mistake 49: Overusing default constructors 7.9 Mistake 50: Failing to maintain the is-a relationship 8 Maintaining the class invariant 8.1 Maintaining the class invariant 8.2 Mistake 51: Writing nonessential accessors 8.3 Mistake 52: Providing trivial mutators 8.4 Mistake 53: Overusing protected instance variables 8.5 Mistake 54: Mistaking operator= and copy constructor semantics
8.6 Mistake 55: Misunderstanding shallow and deep copy semantics 8.7 Mistake 56: Failing to call base class operators 8.8 Mistake 57: Failing to use virtual destructors in polymorphic base classes 8.9 Mistake 58: Calling virtual functions in constructors and destructors 8.10 Mistake 59: Attempting to use polymorphic array elements 8.11 Mistake 60: Failing to initialize all instance variables 9 Class operations 9.1 Mistake 61: Misunderstanding variable shadowing 9.2 Mistake 62: Allowing duplication of unique objects 9.3 Mistake 63: Not coding for return value optimization 9.4 Mistake 64: Not returning a reference from copy assignment operators 9.5 Mistake 65: Forgetting to handle self- assignment 9.6 Mistake 66: Misunderstanding prefix and postfix forms 9.7 Mistake 67: Misleading implicit conversion operators
9.8 Mistake 68: Overusing implicit conversion constructors 9.9 Mistake 69: Focusing too much on standalone operators 9.10 Mistake 70: Failing to mark nonmutating methods constant 9.11 Mistake 71: Not properly marking class methods static 9.12 Mistake 72: Incorrectly choosing between member and nonmember functions 9.13 Mistake 73: Incorrectly returning strings from accessor methods 10 Exceptions and resources 10.1 Using exceptions Affirmation: Intermixed control and recovery paths Objection: Confusing exception handling with normal error handling Objection: Difficulty retrofitting exception handling Affirmation: Ambiguous values Affirmation: Ambiguous data types Affirmation: Enforcing error handling Objection: Providing recovery handlers Affirmation: Transforming failure types Affirmation: Separation of concerns Objection: Encouraging upfront design 10.2 Mistake 74: Not throwing exceptions from constructors 10.3 Mistake 75: Throwing exceptions from destructors
10.4 Mistake 76: Allowing resource leaks when using exceptions 10.5 Mistake 77: Failing to use the RAII pattern 10.6 Mistake 78: Using raw pointers to resources 10.7 Mistake 79: Mixing new and delete forms 10.8 Mistake 80: Trusting exception specifications 10.9 Mistake 81: Failing to throw by value and catch by reference 11 Functions and coding 11.1 Design considerations 11.2 Mistake 82: Using overloaded functions instead of parameter defaulting 11.3 Mistake 83: Failing to use assertions 11.4 Mistake 84: Returning pointers or references to local objects 11.5 Mistake 85: Using output parameters 11.6 Mistake 86: Incorrect use of parameter types 11.7 Mistake 87: Depending on parameter evaluation order 11.8 Mistake 88: Passing excessive parameters 11.9 Mistake 89: Overly long functions with multiple behaviors 11.10 Mistake 90: Overly responsible functions 12 General coding
12.1 Mistake 91: Improperly handling division by zero 12.2 Mistake 92: Incorrectly using the continue keyword in loops 12.3 Mistake 93: Failing to set deleted pointers to NULL 12.4 Mistake 94: Failing to return directly computed Boolean values 12.5 Mistake 95: Underusing expressions 12.6 Mistake 96: Using extraneous else keywords 12.7 Mistake 97: Not using helper functions 12.8 Mistake 98: Wrongly comparing floating- point values 12.9 Mistake 99: Floating-point to integer assignment 12.10 Mistake 100: Ignoring compiler warnings index
front matter preface Learning C++ is mainly about applying its language features in an environment to solve specific problems. Teaching C++ in a college environment differs from mentoring a junior developer in a work environment, yet the language is the same. Think of C++ as the common language (pun intended) that developers speak at the lowest level. Design patterns, conventional use, problem domain specifics, and company processes are higher levels of communication. These higher levels are the most critical; Alan Turing demonstrated that any single computer can compute a solvable problem that any other computer can, differing only in approach and time. Likewise, any language can solve a computational problem that C++ can solve. This thought is not meant to criticize C++ (or any other language) in any way, only to establish that, in a business that uses C++, that fact is of almost no consequence to the overall direction of the company and the problems it solves. Your skill at becoming a seasoned developer is of much greater importance than your (simple?) knowledge of a specific programming language. With all that said, why this book about C++? Earlier, we established that you will be introduced to an environment that uses C++. Given your interest and skills in the
language, you will have the opportunity to apply your knowledge and skills in solving problems that the company cares about. You will be using C++ to do that work. Therefore, knowing how to identify some of the mistakes that are common in C++ gives you the ability to mitigate them and, more importantly, not repeat them. Having to work in a code base that uses specific approaches narrows your opportunity to use C++ in its most expressive and proper way. For example, many string-handling solutions use C idioms, such as strcat, strstr, and strcpy. If this is common practice, you may feel inclined, even pressured, to use the same, although these functions should be avoided in preference to C++ approaches. C++ is a very flexible language, allowing a programmer to do anything made possible by their machine. Many more modern languages abstract away much of the details and complexity of the machine. Notable exceptions are Go and Rust. C++ unapologetically provides the lowest level of detail for manipulating machine characteristics. This approach makes it a compelling language for working with low-level details. However, this flexibility and granularity come at a cost. One cannot program C++ with the “looseness” of Python or Java. For example, C++ provides no default garbage collector to manage memory and resources. The developer must handle these details themselves. Numerous mistakes are made around resource management, which can significantly impact program performance and correctness. It seems appropriate to quote the Spider-Man (2002) movie,
in which Uncle Ben warns, “With great power comes great responsibility.” This quote should have originated with C++. My interest in C++ began with C-Front, Dr. Bjarne Stroustrup’s C++-to-C transpiler. I had already learned and used C, and I’d struggled to get on a project that would use C++. Finally, those projects came along in the late 1980s, when the workstation revolution occurred. Then came Java, around 1995, which abruptly ended my C++ journey. I later picked up projects using C++ in the early 2020s. Concurrently, I was teaching programming at the university level and was able to instruct many C++ classes. In both venues, I began seeing weaknesses, a prevalence of classical C++ issues and idioms, and far too little modern C++; most textbooks barely mention its modern features. Hence, sharing my blunders and discoveries in book form arose. My hope is that students and practitioners will be encouraged to tackle existing code, armed with some background of how much of it got there—warts and all—and how to improve it. If they can avoid these pitfalls, they are well ahead of where many of us started. acknowledgments In a 1624 prose work by English poet John Donne, it was stated that “no man is an island.” We all are interconnected in several ways. Writing a book exposes those interconnections as few other enterprises do.
I wish to acknowledge the Manning editorial and support staff, especially Doug Rudder and Michael Stephens. These gentlemen allowed me to create and bring to fruition a concept, kept me on track, cleaned up my messes, and were genuinely pleasant to work with. Several other team members did their jobs so well that attention was never drawn to them. That does not diminish their effectiveness; it proclaims their professionalism. To the unsung heroes, thanks. My technical editor, Matt Godbolt, was very supportive and thorough. Matt Godbolt is a C++ developer with a passion for striking the balance between readable, maintainable code and high-performance solutions. His sharp eyes detected several mistakes, inconsistencies, and opportunities for improvement. Any remaining errors are my fault. Thanks as well to all the reviewers: Abe Taha, Abel Sen, Abir Qasem, Aldo Biondo, Andre Weiner, Dmitri Nesteruk, Doyle Turner, Frances Buontempo, Francesco Basile, Ganesh Harke, Greg Wagner, Ivan Čukić, Jialin Jiao, John Donoghue, John Villarosa, Juan José Durillo Barrionuevo, Juan Rufes, Keith Kim, Leon Pfletschinger, Luke Kupka, Marcus Geselle, Michael Wall, Narendra Merla, Ofek Shilon, Piotr Jastrzebski, Rajat Kant Goel, Richard Meinsen, Ronaldo Scarpate, Ruud Gijsen, Saboktakin Hayati, Sachin Handiekar, Shantanu Kumar, Shawn Smith, Simone Sguazza, Srinivas Vamsi Parasa, Sriram Macharla, Stanley Anozie, Stefan Turalski, Timothy Jaap van Deurzen, Troi Eisler, and Walt Stoneburner. Your suggestions helped make this a better book.
My family was supportive throughout the entire process. My wife, Kim, helped keep me on task with sympathetic words. My children were always jazzed that their dad was writing a book and encouraged me by keeping me positive about the process (and so many others). Finally, my talents, education, work experience, and much more have been given to me by a gracious Father. One cannot repay such debt; one can only bask in it, be grateful, and try to pass it on (James 1:17). about this book C++ is a multiparadigm language that has existed for much of the computing era. It started as a better C—that is, C with classes—and has become an international standards-based language in active development. At the time of this writing, the C++20 standard was published, the C++23 standard was out for final review, and the C++26 standard was being formed. C++ is used in projects ranging from very small to very large by inexperienced to highly experienced developers and applies to most areas of software development. An estimated tens of billions of lines of C++ code are currently running in production environments. Numerous teams and millions of developers from different backgrounds have written this code over decades. Each developer has their own view of what proper programming models look like, what good C++ code is, and which development methodologies should be used.
Comments 0
Loading comments...
Reply to Comment
Edit Comment