0%

Conquer the Complexity of Modern C++

"Beautiful C++ presents the C++ Core Guidelines from a developer's point of view with an emphasis on what benefits can be obtained from following the rules and what nightmares can result from ignoring them. For true geeks, it is an easy and entertaining read. For most software developers, it offers something new and useful."

--Bjarne Stroustrup, inventor of C++ and co-editor of the C++ Core Guidelines

Writing great C++ code needn't be difficult. The C++ Core Guidelines can help every C++ developer design and write C++ programs that are exceptionally reliable, efficient, and well-performing. But the Guidelines are so jam-packed with excellent advice that it's hard to know where to start. Start here, with Beautiful C++.

Expert C++ programmers Guy Davidson and Kate Gregory identify 30 Core Guidelines you'll find especially valuable, and offer detailed practical knowledge for improving your C++ style. For easy reference, this book is structured to align closely with the official C++ Core Guidelines website.

Throughout, Davidson and Gregory offer useful conceptual insights and expert sample code, illuminate proven ways to use both new and longstanding language features more successfully, and show how to write programs that are more robust and performant by default.

  • Avoid "bikeshedding": stop wasting valuable time on trivia

  • Don't hurt yourself by writing code that will cause problems later

  • Know which legacy features to avoid and the modern features to use instead

  • Use newer features properly, to get their benefits without creating new problems

  • Default to higher-quality code that's statically type-safe, leak resistant, and easier to evolve

  • Use the Core Guidelines with any modern version of C++: C++20, C++17, C++14 or C++11

Whether you've worked with C++ for decades or you've only recently focused on it, there's something here to improve virtually every program you write, design, or maintain.

Table of Contents

  1. Cover Page
  2. Title Page
  3. Contents
  4. Table of Contents
  5. Selected C++ Core Guidelines
  6. Foreword
  7. Preface
  8. Acknowledgments
  9. About the Authors
  10. Section 1 Bikeshedding is bad
    1. Chapter 1.1 P.2: Write in ISO Standard C++
    2. What is ISO Standard C++?
    3. Encapsulating variations
    4. Learning the old ways
    5. Staying on top of developments to the standard
    6. Chapter 1.2 F.51: Where there is a choice, prefer default arguments over overloading
    7. Introduction
    8. Refining your abstraction: Additional arguments h3r overloading?
    9. The subtleties of overload resolution
    10. Back to the example
    11. The unambiguous nature of default arguments
    12. Alternatives to overloading
    13. Sometimes you must overload
    14. Summary
    15. Chapter 1.3 C.45: Don’t define a default constructor that only initializes data members; use in-class member initializers instead
    16. Why have default constructors anyway?
    17. How do you initialize a data member?
    18. What happens when two people maintain a class?
    19. Summary
    20. Chapter 1.4 C.131: Avoid trivial getters and setters
    21. An archaic idiom
    22. Abstraction
    23. Mere Encapsulation
    24. Class Invariants
    25. Nouns and Verbs
    26. Summary
    27. Chapter 1.5 ES.10: Declare one name (only) per declaration
    28. Let me introduce you
    29. Backward compatibility
    30. Writing clearer declarations
    31. Structured binding
    32. Summary
    33. Chapter 1.6 NR.2: Don’t insist to have only a single return-statement in a function
    34. Rules evolve
    35. Ensuring cleanup
    36. Using RAII
    37. Writing good functions
    38. Summary
  11. Section 2 Don’t hurt yourself
    1. Chapter 2.1 P.11: Encapsulate messy constructs, rather than spreading through the code
    2. All in one gulp
    3. What it means to encapsulate a messy construct
    4. The purpose of language and the nature of abstraction
    5. Levels of abstraction
    6. Abstraction by refactoring and drawing the line
    7. Summary
    8. Chapter 2.2 I.23: Keep the number of function arguments low
    9. How much should they earn?
    10. Simplifying matters through abstraction
    11. Do as little as possible, but no less
    12. Real-life examples
    13. Summary
    14. Chapter 2.3 I.26: If you want a cross-compiler ABI, use a C-style subset
    15. Creating libraries
    16. What is an ABI?
    17. Paring back to the absolute minimum
    18. Exception propagation
    19. Summary
    20. Chapter 2.4 C.47: Define and initialize member variables in the order of member declaration
    21. Summary
    22. Chapter 2.5 CP.3: Minimize explicit sharing of writable data
    23. Traditional execution model
    24. Wait, there’s more
    25. Avoiding deadlocks and data races
    26. Setting aside locks and mutexes
    27. Summary
    28. Chapter 2.6 T.120: Use template metaprogramming only when you really need to
    29. std::enable_if => requires
    30. Summary
  12. Section 3 Stop using that
    1. Chapter 3.1 I.11: Never transfer ownership by a raw pointer (T*) or reference (T&)
    2. Using the free store
    3. The performance cost of smart pointers
    4. Using unadorned reference semantics
    5. gsl::owner
    6. Summary
    7. Chapter 3.2 I.3: Avoid singletons
    8. Global objects are bad
    9. Singleton Design Pattern
    10. Static initialization order fiasco
    11. How to hide a singleton
    12. But only one of these should ever exist
    13. Wait a moment…
    14. Summary
    15. Chapter 3.3 C.90: Rely on constructors and assignment operators, not memset and memcpy
    16. Chasing maximum performance
    17. The horrendous overhead of the constructor
    18. The simplest possible class
    19. What is the standard talking about anyway?
    20. But what about memcpy?
    21. Never underestimate the compiler
    22. Summary
    23. Chapter 3.4 ES.50: Don’t cast away const
    24. Story time
    25. Dealing with rather more data
    26. The const firewall
    27. Implementing a dual interface
    28. Caching and lazy evaluation
    29. Two types of const
    30. Surprises with const
    31. Summary
    32. Chapter 3.5 E.28: Avoid error handling based on global state (e.g. errno)
    33. Error handling is hard
    34. C and errno
    35. Return codes
    36. Exceptions
    37. <system_error>
    38. Boost.Outcome
    39. Why is error handling so hard?
    40. Light at the end of the tunnel
    41. Summary
    42. Chapter 3.6 SF.7: Don’t write using namespace at global scope in a header file
    43. Don’t do this
    44. Disambiguation
    45. Using using
    46. Where do the symbols go?
    47. An altogether more insidious problem
    48. Solving the problem of cluttered scope resolution operators
    49. The temptation and The Fall
    50. Summary
  13. Section 4 Use this new thing properly
    1. Chapter 4.1 F.21: To return multiple “out” values, prefer returning a struct or tuple
    2. The shape of a function signature
    3. Documenting and annotating
    4. Now you can return an object
    5. You can also return a tuple
    6. Passing and returning by non-const reference
    7. Summary
    8. Chapter 4.2 Enum.3: Prefer class enums over “plain” enums
    9. Constants
    10. Scoped enumerations
    11. Underlying type
    12. Implicit conversion
    13. Summary
    14. Postscript
    15. Chapter 4.3 ES.5: Keep scopes small
    16. The nature of scope
    17. Block scope
    18. Namespace scope
    19. Class scope
    20. Function parameter scope
    21. Enumeration scope
    22. Template parameter scope
    23. Scope as context
    24. Summary
    25. Chapter 4.4 Con.5: Use constexpr for values that can be computed at compile time
    26. From const to constexpr
    27. Default C++
    28. Using constexpr
    29. inline
    30. consteval
    31. constinit
    32. Summary
    33. Chapter 4.5 T.1: Use templates to raise the level of abstraction of code
    34. Story time
    35. Raising the level of abstraction
    36. Function templates and abstraction
    37. Class templates and abstraction
    38. Naming is hard
    39. Summary
    40. Chapter 4.6 T.10: Specify concepts for all template arguments
    41. How did we get here?
    42. Constraining your parameters
    43. How to abstract your concepts
    44. Factoring via concepts
    45. Summary
  14. Section 5 Write code well by default
    1. Chapter 5.1 P.4: Ideally, a program should be statically type safe
    2. Type safety is a security feature of C++
    3. Union
    4. Casting
    5. Unsigned
    6. Buffers and sizes
    7. Summary
    8. Chapter 5.2 P.10: Prefer immutable data to mutable data
    9. The wrong defaults
    10. const ness in function declarations
    11. Summary
    12. Chapter 5.3 I.30: Encapsulate rule violations
    13. Hiding the unsightly things in life
    14. Keeping up appearances
    15. Summary
    16. Chapter 5.4 ES.22: Don’t declare a variable until you have a value to initialize it with
    17. The importance of expressions and statements
    18. C-style declaration
    19. Declare-then-initialize
    20. Maximally delayed declaration
    21. Localization of context-specific functionality
    22. Eliminating state
    23. Summary
    24. Chapter 5.5 Per.7: Design to enable optimization
    25. Maximizing the frame rate
    26. Working further from the metal
    27. Optimization through abstraction
    28. Summary
    29. Chapter 5.6 E.6: Use RAII to prevent leaks
    30. Deterministic destruction
    31. Leaking away files
    32. Why are we bothering?
    33. This all seems a bit much: Future possibilities
    34. Where can I get this?
  15. Envoi
  16. Afterword
18.119.253.93