[content]
Item 1. View C++ as a federation of languages
C++ is a multi-paradigm programming language, which has following features
- Procedural
- Object-oriented
- Functional
- Generic
- Meta-programming
C++ contains following primary sub languages
- C
- Object-oriented c++
- Template C++
- STL
Item 2. Prefer consts, enums and inline to #defines
DO: Use const pointer that points to const object
const char* const pointer = "";
DO: Use “static const” to ensure at most one copy of the member in the class
static const int numTurns = 5;
DO: Enum hack. The values of an enumerated type can be used where ints are expected.
1. The enum hack behaves in some ways more like a #define than a const. Enums are not lvals. We cannot get the address of an enum.
2. Enum hack is a fundamental technique of template meta-programming. (static member can also be used nowadays, ref)
enum { NumTurns = 5}; // make NumTurns a symbolic name for 5
int scores[NumTurns]; // fine
DO: use inline template function instead of Macro functions. You get the efficiency of a macro plus all the predictable behavior and type safety of a regular function.
template<typename T>
inline void callWithMax(const T& a, const T&b) {
f(a > b ? a : b);
}
WHY:
1. Prefer compiler to the preprocessor. The Macro name are not in the symbol table, hence hard to debug.
2. #define does not respect scope. Once macro is defined, it is in force for the rest of the compilation.
Item3: Use const whenever possible
DO: const pointer, pointer to const value, const iterator, iterator to const value, functions that return const value, const member functions.
// Functions that return const value
class Rational {...};
const Rational operator*(const Rational& lhs, const Rational& rhs);
if (a * b = c) ... // Error: meant to do a comparison, but it can be detected by compiler
WHY: Different const member functions.
Bitwise constness (physical constness) v.s. logical constness
1. Bitwise constness: a member function is const if and only if it does not modify any of the object’s data member. If we have pointers as data member, we might be able to change the underlying data but still keep the pointers unchanged.
2. Logical constness: a const member function can modify some bits but in ways clients cannot detect.
3. Compiler enforces bitwise constness but we should try to achieve logical constness.
Item4: Make sure objects are initialized before they’re used
DO: Prefer true member initialization (via an initialization list) to pseudo-initialization via assignment.
DO: Non-local static object should be defined in its own function, the function returns reference to the static object. (This solves the un-initialization issue for non-local static object. Before C++11, this approach will still be vulnerable in multi-thread setting. Because there could be multiple thread initiating the same non-local static object. But after C++11, there is guaranteed one initializer)
DO: De-constructor could be trouble some for non-local static object in multi-thread setting too. It is unclear which threads will finally deconstruct it. Therefore, we shouldn’t de-construct the non-local static object in our program.
WHY:
1. Initialization order for an object is fixed. Base classes are initialized before derived classes and within a class, data members are initialized in the order in which they are declared.
2. A static object is one that exists from the time it is constructed until the end of the program.
2.1 Stack and heap-based objects are not static objects.
2.2 Global objects, objects defined at namespace scope, objects declared static inside classes, inside functions or at file scope are static objects.
3. The initialization order for a non-local static object is undefined. If initialization of a non-local static object in one translation unit uses a non-local static object in a different translation unit, the object it uses could be uninitialized.
4. But the local static objects are guarantee to be initialized when the object’s definition is first encountered during a call to that function. (Concurrent initializer issue before C++11 but not after C++11)