Base idea:
- readable, maintainable, reusable code
C/C++:
- no copy-paste excesses
- use variables
- use functions
- use functions instead of abusing function macros
- use enums and constants instead of abusing #defines
- use stdint.h or similar typedefs as appropriate
- actually use unsigned types where appropriate
- declare variables at the innermost possible scope (unless that would mean unnecessary repeated constructor calls)
- directly initialize variables and structure members at point of declaration (C++: NSDMI)
- compile with all useful warnings enabled and configured as errors
- some useful warnings are not even included with -Wall -Wextra, like -Wshadow -Wsign-conversion (-Wconversion)
- use comments to support the code reader
- high level explanations for the why
- document assumptions
- don't repeat what is already obvious from the code, use descriptive function names etc. instead
- make assumptions explicit with assert/static_assert/etc.
- don't use postincrement where preincrement is meant
- limit code nesting, i.e. use early exits, separate functions etc.
- attach * and & to the type, not the variable!
- variables and function names never start with a capital letter!
- preferably use camelCase/PascalCase names to distinguish variables/names and types
- no hungarian naming with type prefixes like
float fValue- nobody updates these names when types change
- the name should be descriptive enough you don't even need to know the type in general
- modern IDEs show you the declaration if needed
- prefer Allman style
- but no braces needed if the statement body is only 1 line
- properly use static to mark module-private functions
- no need to make code unreadable just to follow '70s limitations of 80 characters per line
C++ specific:
- in general use modern C/C++ features to your advantage
- initialize all class members in the class
- use of unique_ptr to make ownership explicit, also as parameter types
- e.g.
void foo(std::unique_ptr<T> p);propagates that info to callsitefoo(std::move(p)); - use unique_ptr<T[]> instead of raw arrays
- e.g.
- no raw new/delete
- use override (and no virtual) on all overriding methods
- use final to mark all leaf classes
- self-documenting
- subclassing should only be allowed if a class is specifically designed for that
- enables devirtualization and thus inlining