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

    Memory (Basics)Memory (Basics)Memory

    Organisation

    Goals

    • lots of space (all of a machine's main memory if we want)
    • fast allocation and access
    • potentially indefinite object lifetime (as long as the program runs)
    • avoid unnecessary memory overhead: de-allocate objects as soon as they are no longer needed
    • avoid runtime overhead for memory management

    It is unfortunately almost impossible to fulfill all these goals at the same time!

    Solution: Two Memory Partitions Two Parts

    The stack is used for automatic, scoped-based allocation and de-allocation of local variables (including function parameters):

    Use the navigation buttons on the right/left to go forward/backwards.

    std::vector's Memory vector's Memory std::vector

    std::vector Memory Layout Layout

    Each vector object holds a separate buffer on the heap where the actual content is stored.

    Right now we only know how to allocate objects on the stack, but the vector object v itself could also be allocated on the heap (more on that in later chapters).

    vector<int> v {0,1,2,3,4};

    std::vector Growth Scheme Growth

    Memory blocks, once allocated, can't be resized! (operating system does not guarantee there is space left after memory block)

    Dynamic array implementations separate the array object from the actual memory block for storing values.

    Growth is then done the following way:

    • allocate new, (≈1.1-2×) larger memory block
    • copy/move old values to new block
    • destroy old, smaller block

    std::vector Size vs. Capacity Size/Capacity

    • .size() number of elements in vector
    • .resize(new_number_of_elements)

    • .capacity() number of avail.available memory slots
    • .reserve(new_capacity)
    
    vector<int> v;
    v.reserve(4);
    v.push_back(1);
    v.push_back({2,3});
    
    auto s = v.size(); auto c = v.capacity();
    v.resize(6,0);
            capacity size
    
    • 1 0
    • 4 0
    • 1
    • 4 1
    • 1
    • 2
    • 3
    • 4 3

    s: 3 c: 4
    • 1
    • 2
    • 3
    • 0
    • 0
    • 0
    • 6 6

    If you know the (approximate) number of elements in advance ⇒ reserve before adding elements to the vector!

    This avoids unnecessary memory allocations and copying during the growth phase. See here for a short explanation.

    Use the navigation buttons on the right/left to go forward/backwards.