Beginner's Guide
    First Steps
    Input & Output
    Custom Types – Part 1
    Diagnostics
    Standard Library – Part 1
    Function Objects
    Standard Library – Part 2
    Code Organization
    Custom Types – Part 2
    Generic Programming
    Memory Management
    Software Design Basics

    Aggregate Types Aggregate Types Aggregates

    Type Categories (simplified) Type Categories

    Fundamental Types
    void, bool, char, int, double, …
    Simple Aggregates

    Main Purpose: grouping data

    • aggregate: may contain one/many fundamental or other aggregate-compatible types
    • no control over interplay of constituent types
    • trivial if only (compiler generated) default construction / destruction / copy / assignment
    • standard memory layout (all members laid out contiguous in declaration order), if all members have same access control (e.g. all public)
    More Complex Custom Types

    Main Purpose: enabling correctness/safety guarantees

    • custom invariants and control over interplay of members
    • restricted member access
    • member functions
    • user-defined construction / member initialization
    • user-defined destruction / copy / assignment
    • may be polymorphic (contain virtual member functions)

    How To Define / Use Definition

    Why Custom Types / Data Aggregation? Why Custom Types? Why?

    • semantic data grouping: point, date, …
    • avoids many function parameters and thus, confusion
    • can return multiple values from function with one dedicated type instead of multiple non-const reference output parameters
    void closest_point_on_line (double lx2, double ly1, double lx2i, double ly2, double px, double py, double& cpx, double& cpy) { … }
    • many parameters of same type ⇒ easy to write bugs
    • non-const reference output parameters ⇒ error-prone
    • internal representation of a line is also baked into the interface
    struct point { double x; double y; };
    struct line  { point a; point b; };
    point closest_point_on_line (line const& l, point const& p) { … }
    • straight-forward interface
    • easy to use correctly
    • If internal representation of line changes (e.g., point + direction instead of 2 points) ⇒ implementation of closest_point_on_line needs to be changed too, but its interface can stay the same ⇒ most of calling code doesn't need to change!

    Aggregate Initialization Initialization

    • brace-enclosed list of member values
    • in order of member declaration
    enum class month {jan = 1, feb = 2,…, dec = 12};
    struct date {
      int yyyy;
      month mm;
      int dd;
    };
    int main () {
      date today {2020, month::mar, 15};	
      // C++98, but also still OK:
      date tomorrow = {2020, month::mar, 16};	
    }

    Compounds

    Example: date as member of person
    enum class month { jan=1, feb=2,… , dec=12 };
    struct date {   
      int yyyy;
      month mm;
      int dd;
    };
    struct person {
      std::string name;
      date bday;
    };
    int main () {
      person jlp { "Jean-Luc Picard",              {2305, month::jul, 13} };
      cout << jlp.name;     // Jean-Luc Picard
      cout << jlp.bday.dd;  // 13
      date yesterday { 2020, month::jun, 16 };
      person rv = { "Ronald Villiers", yesterday };
    }

    Copying

    Copies are always deep copies of all members!
    enum class month {jan = 1, … };
    struct date { 
      int yyyy;  month mm;  int dd; 
    };
    int main () {
      date a {2020, month::mar, 7};     
      date b = a;  // deep copy of a
      b.dd = 22;   // change b
    }
    • Copy Construction = create new object with same values as source
    • Copy Assignment = overwrite existing object's values with that of source
    struct point { int x; int y; };
    point p1 {1, 2};  // construction
    point p2 = p1;    // copy construction
    point p3 ( p1 );  // copy construction
    point p4 { p1 };  // copy construction
    auto  p5 = p1;    // copy construction
    auto  p6 ( p1 );  // copy construction
    auto  p7 { p1 };  // copy construction
    p3 = p2;  // copy assignment
              // (both p2 & p3 existed before)

    Value vs. Reference Semantics Value/Reference Semantics Value Semantics

    = variables refer to objects themselves:

    • deep copying: produces a new, independent object; object (member) values are copied
    • deep assignment: makes value of target equal to that of source object
    • deep ownership: member variables refer to objects with same lifetime as containing object
    • value-based comparison: variables compare equal if their values are equal

    Value semantics is the default behavior for fundamental types (int, double, etc.) in almost all programming languages and also the default for aggregates/user-defined types in C++.


    = variables are references to objects:

    • shallow copying: copies of a variable refer to the same object
    • shallow assignment: assignment makes a variable refer to a different object
    • shallow ownership: member variables are also just references
    • identity-based comparison: variables compare equal if they refer to the same object

    Most other mainstream languages (Java, Python, C#, Swift, …) use (baked-in) reference semantics for user-defined types.


    • default: value semantics for all types (except C-style arrays)
    • optional reference semantics possible for all types (by using references or pointers)

    std::vector of Aggregates vector of Aggregates inside std::vector

    • vector<T>'s storage contains objects of type T themselves, not just references or pointers to them (as in Java/C#/…)
    • if vector object gets destroyed ⇒ contained T objects get destroyed

    The Most Vexing Parse

    Can't use empty parentheses for object construction due to an ambiguity in C++'s grammar:

    struct A { … };
    
    A a (); // declares function 'a' // without parameters // and return type 'A'
    A a; // constructs an object of type A
    A a {} // constructs an object of type A