Part 2

Memory

In programming, we work with a lot with RAM. RAM is fast to use and access than a Hard Drive.

One thing is quicker… Registers

C++ has a way to suggest to the compiler that a var should live in a register instead of RAM Register keyword:

This, however, has no functionality It suggests to the compiler that this var is going to be used a LOT, but doesn’t actually force any change

Pointers

Variables consist of:

Address is how we refer to the location and the location is the actual location

Pointers in the Library

The pointer is the index card in the Catalogue of the library

Index card gives all the information about the book and tells you where it is and how to get it

Pointers

They have the same properties as the variable

This means we can have Pointers to pointers… Pointers are also variables

Why use Pointers?

Humans are good at remembering names, machines only work in addresses Pointers give us both by providing a name to an address…

We work purely with addresses in pointers, but we also have the ability to access and work with the info the pointer is going towards Operators:

What is a pointer? A variable that stores an address

Byte-Addressable Memory

Visualization

Think of people going to the Olympics

  1. People come from wherever they live to a hotel/venue (disk)
  2. Then they get to their floor and room number (address)
  3. Eventually called to their event and waiting area (registers)
  4. Complete the venue/task (CPU)

Understanding this can help us understand pointers as well

Pointers and Byte-Addressable Memory

We have two types of pointers

An int takes up 32 bits of memory (4bytes) A char only takes 8 bits or 1 byte

When we add 1 to a pointer we are moving it “one full data-type”

C/C++ Arrays and Strings

Most fundamental data structure Arrays in many languages are similar with minor differences

Basic Understanding

Visualization Think of an apartment building There are dozens of people living in a single apt building The building only has one address, with all individuals inside it However, each person inside this one address can be found through a specific unit

Arrays

There are 2 types of arrays Arrays at Compile Time

Create during Runtime

Basic Array Creation

Declaraing an array:

Unlike Java, the array is not filled with anything. If you output the array, C/C++ will attempt to make the bits in RAM at that point

Accessing Array Values

{

    int myArray[10];
    for (int index = 0; index < 10; index++)
    {

        myArray[index] = index;

    }

}

Arrays are not automatically bound checked We must keep track of the bounds through variables, constants or #defined macro constants

{

    const int SIZE = 5;
    int array[SIZE];

    for(int index = 0; index < SIZE; index++)
    {

        cout << array[index] << endl;

    }

}

If we don’t bound check our selves C/C++ will continue reading into RAM

Multiple Dimensions

2D Array

3D Array

{

    int twoD[4][4];
    for(int i = 0; i <4; i++)
    {

        for(int j = 0;j < 4; j++)
        {

            twoD[i][j] = j+i;

        }

    }

}

Initializing an Array

int array[10] = {1,2,3,4,5,6,7,8,9,10};

We can initialize multidimenstional arrays with nesting lists int array[3][3] = 1,2,3 ; 4,5,6

Arrays - Strings vs. Chars

There are two ways of initializing arrays of character in declaration

char s1[ ] = {'a', 'l', 'p', 'h', 'a'}; //as an array of char char s2[ ] = "alpha"; //as a string

These two initializations have different results in memory s1(“alpha”) has a size of 5 s2(“alpha\0”) has a size of 6

The first item initializes that array as a character array rather than a String

s2 initializes it as a String and therefore automatically adds the ‘\0’ character into the data

Truncated Initialization If the size of the array is specified and there is not enough space, the null charf will not be attached to the string

char s2[5] = "alpha"; will not attach this because there is not enough room. We specified a length of 5 and we need the ‘\0’ at length 6

Arrays and Sizing

In C/C++ there is a command that gets the size of Compile Time created arrays

This command gives us the size in bytes of the target that is passed in size = sizeof(array); / (sizeof(datatype)); sizeof(array[0]);

Dynamic Allocated Arrays

These are used when we don’t know the size of the data that we are going to be working with. When we don’t know the size of the data we cannot allocate the array during compile time

You cannot create an array with an unknown size:

If we guess, problems of too large and too small will occur

How do we solve this issue? Pointers Remember: a pointer stores a memory address

  • An array reference is the memory address of the first element
  • A pointer can point to an array

C/C++ has different ways of doing this

C Style Dynamic Arrays

malloc()

malloc() returns a void pointer Void is an undefined data type

The malloc command needs to be casted into the type that we want it to be

We use the free() command to release the memory

Making an Array

{
   int* myArray;
   int size = 10;

   myArray = (int*) malloc(size * sizeof(int)); 
}
  1. Malloc sets aside a number of bytes
  2. We need an array of integers, so we need enough bytes to store those integers
  3. So we multiply the number of integers we want, by the size of the integers
  4. This memory gets allocated as a void pointer
  5. We cast the void pointer to an integer pointer
  6. We give the new integer pointer to our array pointer

Make in C++

{
    int* myArray = new int[10]
}

Looks a lot more like Java, no data caluculation like malloc

To frree space we use the delete command

{
    int* myArray;
    int size = 10;

    myArray = (int*) malloc(size * sizeof(int));
    for(int c = 0; c < size; c++)
	    myArray[c] = c;
}

In C/C++ and other languages [] is actually an operator! In the context of a statement such as myArray[c] they are in pointer notation

[] vs *

It is quicker to traverse memory by using pointer notation (*) instead of brackets [] adds extra code since it has to be recognized and replaced in compilation Using your pointers to navigate through memory is faster by fractions of a second

CAUTION

We are now in the territory of managing our own memory which means we must be more aware of scope and how it is used. Running through a loop that is local scoped rather than block scoped, when we don’t dump our memory

Memory Management

Golden Rule - “Whenever we dynamically allocate memory we MUST give it back” Dynamically allocated memory is given a specific location in RAM When we allocate from that part of RAM we have to free that memory back up so it can be used again

The HEAP

The heap is used for dynamic allocation in Java the JVM creates a Heap for grabage collection and memory allocation The heap is allocated during run-time through dynamic allocation, but it also needs to be managed during run-time This is where grabage collection and memory management comes in

Don’t trust Sizeof

The sizeof() function is useless when it comes to dynamic arrays

Due to the creation of a dynamic array through the use of pointers we have to navigate through that pointer

{
    int* myArray = new int[10]; //40 bytes of ints?
    cout << sizeof(myArray) << endl; // output ... 4 ...
}

It’s size is the same size of an int… even when pointing to an array

Multi-Dimention Dynamics

Arrays of Arrays

In java we can make something called a “ragged array” This is where we create a multi-dimentional array but the “2D” portion isn’t the same size

In Java this is very easy to create because they are objects here

{
    int[][] array = new int[10][];
    for(int c = 0; c < 10; c++)
    {

        array[c] = new int[c+5];

    }
}

When we work with String, there is little dynamic to it char string[] = "Hi there";

Dynamic 2D

When creating a C/C++ array, we have to use pointers

Why use a pointer to a pointer? When creating a dynamic array, we need to specift the datat type that we are pointing to

Creating a Dynamic 2D array

  1. Make the pointer array ```cpp {

    //C++ code int** myArray; myArray = new int*[size]

    //C code int** myArray; myArray = (int*)malloc(size * sizeof(int));

}

With a arbitrary amount of pointers we can create an arbitrary pile of single dimensional Arrays!

2. Create sub arrays

```cpp
{

    //C++ Code
    for (int row = 0; row < size; row++)
    {

        myArray[row] = new int[items];

    }

    //C Code
    for (int row = 0; row < size; row++)
    {

        myArray[row] = (int*)malloc(items*sizeof(int));

    }

}

This can also be done for 3D and 4D arrays

This is not however, it is pass by address/pointer We can change contents of an array, but we cannot change the array itself

Passing Arrays in Java

We pass by constant reference

Pass by Reference Safety

We can make apssing by refence safe The main drawback ehre is the possibility of side-effects

We can avoid this by making our Reference Parameters into Constant reference params Use const in our keywork, this makes the reference into a constant

Pass by Address/Pointer

Passing a pointer allows us to tow the line between value and reference We are still working with memory addresses but working indirectly The pointer that is passed is passed by value

void doStuff(int* val); Pass a pointer directly, or the reference to the variable

Pointers and References

A pointer is a variable that holds a memeory address

A reference is a “variable” which ‘refers to’ another named variable

ISSUES

If a pinter is passed that means anything that fits will go through

Passing a pointer is excellent for passing single dimension arrays Multidimension are a little different

Final Guide

Pass by a constant pointer when:

Pass by pointer when:

Pass by contant reference when:

Pass by reference when: