Feb 14, 2022

[C++][book review] Beautiful C++

Reference:
[Book] https://www.amazon.com/Beautiful-Core-Guidelines-Writing-Clean/dp/0137647840
[Cpp core guideline] https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#main



F.51: Where there is a choice, prefer default arguments over overloading

C.45: Don’t define a default constructor that only initializes data members; use in-class member initializers instead

C.131: Avoid trivial getters and setters

ES.10: Declare one name (only) per declaration

NR.2: Don’t insist to have only a single return-statement in a function

P.11: Encapsulate messy constructs, rather than spreading through the code

I.23: Keep the number of function arguments low

Do as little as possible, but no less
x64 ABI, there is a four-register fast-call calling convention by default.
A four-parameter function will execute slightly faster than a function taking a class by reference.

I.26: If you want a cross-compiler ABI, use a C-style subset

C.47: Define and initialize member variables in the order of member declaration

CP.3: Minimize explicit sharing of writable data

CP.22: Never call unknown code while holding a lock (e.g., a callback)
"Don’t communicate by sharing memory; share memory by communicating"

T.120: Use template metaprogramming only when you really need to

Meta-programming techniques, while useful, have been adopted into the lan- guage more explicitly.
consider using concept in C++20.

I.11: Never transfer ownership by a raw pointer (T*) or reference (T&)

Your default choice for holding objects with dynamic storage duration should be a std::unique_ ptr.
You should only use std::shared_ptr where reasoning about lifetime and ownership is impossibly hard, and even then, you should treat it as a sign of impending technical debt caused by a failure to observe the appropriate abstraction.

Use GSL:
http://github.com/Microsoft/GSL

I.3: Avoid singletons

C.90: Rely on constructors and assignment operators, not memset and memcpy

ES.50: Don’t cast away const

ES.5: Keep scopes small

CP.43: Minimize time spent in a critical section

E.28: Avoid error handling based on global state (e.g. errno)

You do not know how your calling code is going to respond to errors.
You cannot rely on your caller handling the error.

SF.7: Don’t write using namespace at global scope in a "header file"

F.21: To return multiple “out” values, prefer returning a struct or tuple

Enum.3: Prefer class enums over “plain” enums

ES.5: Keep scopes small

only declare auto-variables that is close to its use. (Golang)

Con.5: Use constexpr for values that can be computed at compile time

T.1: Use templates to raise the level of abstraction of code

T.10: Specify concepts for all template arguments (C++20)

P.4: Ideally, a program should be statically type safe

Problem areas:

  • unions - use variant (in C++17)
  • casts - minimize their use; templates can help
  • array decay - use span (from the GSL)
  • range errors - use span
  • narrowing conversions - minimize their use and use narrow or narrow_cast (from the GSL) where they are necessary
If you are doing any arithmetic, including comparison, use a signed type. If you are using an unsigned type to get an extra bit of representation, you are using the wrong type and you should go wider or recognize that you are performing a very risky optimization.


P.10: Prefer immutable data to mutable data

I.30: Encapsulate rule violations

ES.22: Don’t declare a variable until you have a value to initialize it with

Declaring at point of use improves readability of code, and not declaring state at all improves things even further. Reasoning about state requires a comprehensive memory, which is a diminishing asset as codebases expand.

Per.7: Design to enable optimization

E.6: Use RAII to prevent leaks

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.