Book Notes: A Tour of C - tnballo/notebook GitHub Wiki

References:

  1. Stroustrup, Bjarne. A Tour of C++, Addison-Wesley, 2018.

Chp. 3 - Modularity


  • modules (C++20) are a replacement for #includes that doesn't require seperation into header (.h) and source (.cpp) files. Benefits are faster compilation (once, rather than per translation unit) and maintainability (no transitive imports or macro overriding) (pg. 32).

  • Namespaces ensure symbols don't conflict and help with component organization. The using directive makes unqualified names accessible, for brevity, within it's scope, ex. using namespace std; (pg. 34).

  • throw transfers control, via stack unwinding, to the exception handler for the exception type specified by it's operand (see <stdexcept> for built-in exception types) (pg. 36).

  • Functions declared with noexcept can never throw an exception, instead calling std::terminate() immediately (pg. 37).

  • Unlike C, where malloc's caller is responsible for checking for a NULL return, C++'s new will throw std::bad_alloc if heap memory has been exhausted (pg. 37).

  • RAII (Resource Acquisition Is Initialization) is a paradigm in which the constructor is responsible for checking invariants and then acquiring all resources necessary for a class (ex. allocate heap memory, open socket, open file) and the destructor releases them. This design is preferable to overuse of try blocks (pg. 36).

  • assert checks conditions at runtime, static_assert checks compile-time properties that can be expressed as constexpr (ex. size of an integer on a given system, types used as parameters in generic programming) (pg. 40).

  • As a rule of thumb, if data is larger than 2-3 pointer sizes for a given system it should be passed by reference, not by value. Where possible, pass by const reference (pg. 42).

  • A function declaration can specify a default parameter value to use if that parameter isn't provided (ex. void print(int value, int base = 10); allow calls print(x, 16) and print(x)). This is cleaner than using overriding for the same purpose (pg. 43).

  • Structured binding allows giving local names to members of a class object or struct, which can be useful for returning or iterating over "multiple values" (in the form of a singular object/struct). Ex (pg. 45):

void incr(map<string,int>& m)
{
    for (auto& [key,value] : m)
    {
        ++value;
    }
}

// Assume Entry is a struct with a string name and an int value
// Assume read_entry() populates a struct from an input stream and returns it by value
auto [name, value] = read_entry(cin)
⚠️ **GitHub.com Fallback** ⚠️