Beginner's Guide
    First Steps
    Input & Output
    Basic Custom Types
    Diagnostics
    Standard Library
    Code Organization
    Powerful Custom Types
    Generic Programming
    Memory Management
    Software Design Basics

    Simple Aggregate TypesSimple Aggregate TypesAggregates

    Type Categories (simplified) Type Categories

    Fundamental Types
    void, bool, char, int, double, …
    Simple Aggregates
    PODs (Plain Old Data Types)
    • may contain one/many fundamental or other types (that can be initialized in an aggregate-compatible way)
    • default construction / destruction / copy / assignment
    • standard memory layout
    • unrestricted member access
    • no user-defined member initialization
    Non-Trivial Types

    may have/be

    • member functions / restricted member access
    • user-defined construction / member initialization
    • user-defined destruction / copy / assignment
    • non-standard memory layout
    • polymorphic (contain virtual member functions)

    Simple Aggregates / PODs PODs

    Example: Type point with 2 integer coordinates
    struct point {
      int x;  // ← "member variable"
      int y; 
    };
    
    // create new object (on stack) point p {44, 55};
    // read members' values cout << p.x <<' '<< p.y; // 44 55

    Member variables are stored in the same order as they are declared.

    -7682STACK
    23988
    p.y 55 top
    p.x 44

    Assigning to member values:

    p.x = 10;
    p.y = 20;
    cout << p.x <<' '<< p.y;  // 10 20
    -7682STACK
    23988
    p.y 20 top
    p.x 10

    Fundamental types are not default-initialized ⇒ members get whatever value was in memory at the time:

    point u;      // uninitialized
     cout << u.x;  // random value!
    141STACK
    u.y -7682 top
    u.x 23988
    p.y 20
    p.x 10

    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 ⇒ implementation of closest_point_on_line needs to be changed too, but interface does not ⇒ calling code can stay the same most of the times!

    Aggregate Initialization Initialization

    Type { arg1, arg2, …, argN }
    • 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 }

    State after last line of main:

    STACK
    b.dd 22 top
    b.mm 3
    b.yyyy 2020
    a.dd 7
    a.mm 3
    a.yyyy 2020
    • 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)

    std::vector of PODs 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
    vector<int> v { 0,1,2,3,4 };
    struct p2d { int x; int y; };
    vector<p2d> v {{1,2},{5,6},{8,9}};

    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
    More (more advanced material)(skips ahead to more advanced material):