The bulletin board

•      Compilers and lab instructions can be found here

•      You can post to the bulletin board; either questions or answers, or something cool you think other students would like.

Pointers  --  Chapter 3 Weiss  Chapter 10 Lafore

 

Why does C++ use pointers

•      Pointers are used a lot in accessing array elements in older C++ or C code

•      They are also used to pass arguments to a function where the argument needs to be changed

•      They are used to access dynamic variables or objects (stored on the heap)

•      Used in data structures like linked lists and trees

 

Some simple concepts

•      Every byte in a computer’s memory has an address

•      When a program is loaded into memory, it occupies a certain range of addresses on the runtime stack

•      Every variable or functions starts at a certain address

•      This address is stored in a symbol table with the variable or function name so you can use the variable name to directly access the value stored there

•      But it is also possible to have addresses stored as the value of variables;

–    in this case you can indirectly access the value of the variable whose address is stored there

 

Using addresses in C++

•      There are two new operators that are used with addresses in C++

–   The  &, address-of operator

–   The *, which is used in two ways with pointers

•   It is used to declare pointer variables

•   It is also used to dereference pointer variables;

–   To dereference means to return the value at the address in the pointer variable

 

 

The address-of operator

•      You can find the address of a variable by using the address-of operator &

•      Run this program:
varadd.cpp

#include <iostream>
using namespace std;

int main()
   {
     int var1 = 11, var2 = 22;
     int var3 = 33;

   cout << &var1 << endl
           << &var2 << endl
           << &var3 << endl;
   return 0;
   }

 

 

Pointer Variables

•      Pointer variables contain memory addresses as their values.

•      Declaring pointer variables

–    This is the first use of the * operator

•      A pointer is declared to contain the address of a certain data type

      int* valPtr, val1;

      int* xPtr * yPtr;

      float* zPtr;

•      A pointer can only contain the address of that particular data type

•      Pointers should be initialized to 0 or null

xPtr = 0;   // initialize to null
xPtr = NULL

 

The danger of uninitialized pointers

•      Even if you do not give a pointer a value, it is still pointing at something.

•      Most of the time this will cause your program to crash, because the address it points to will not make sense in your program

•      But sometimes it may not cause a crash

–    This will make your program do strange things, but may not crash until later, or at all

•      If you are changing something that the pointer points to, it may not show up until later in your program

–    This is a very hard runtime error to find, since the source of the error, and where it shows up may be far apart.

 

Accessing the variable pointed to

•      The pointer is dereferenced  to access the variable it points to

–    The dereference operator is the *

•       An example

   int main()
{
   int var1, var2;       
   int* ptr;               

   ptr = &var1;
  *ptr = 37;
   var2 = *ptr; 
   cout << var2 << endl;
   return 0;
 }

// notice that all these are stored on the runtime stack;
i.e. statically

 

Summary so far

&  Returns the address  of its operand

* Is used to declare a pointer

* Returns the contents of the address it stores

–    Called the dereferencing operator

•    int y = 5;
int *yPtr;
yPtr = &y;

•      Examples of pointer use
cout<< *yPtr <<endl;
*yPtr = 9;
cin >> *yPtr;

 

Using pointers

Assume we these declarations:

•    int y = 5, x = 8;
int *ptr;
ptr = &y;

•      What is the result of each of these statements?

ptr = x;  //error

*ptr = x;

ptr = &x;

*ptr +=6;

cout << x  << y;

cout << *ptr;

 

 

Drawing diagrams

•      You will find you will make fewer errors with pointers if you draw diagrams to show exactly what is happening.

•      Draw diagrams for the following: (this was the quiz we did in class)

int x = 12, y = 7;

int  *pt1,  *pt2 ;

pt1 = &x;  pt2 = &y;

*pt1+=3;  

pt2 = pt1;

*ptr2 = 28;

cout << *pt1<< *pt2;

cout << x << y;

pt2=&y;

*pt2=*pt1;

*pt2 +=2;

cout << *pt1<< *pt2;

 

The stack and heap

•      Terminology

–   Static RAM is often called the runtime stack

•   The program itself, functions,  and named variables are stored on the runtime stack

–   Dynamic RAM is called the memory heap

•   This is memory available from the OS to be allocated to programs as they execute

•      One of the main uses of pointers is to access data allocated on the heap.

 

Memory management

•      Like Java, objects can be created on the heap by calling new

•      The result of new is a pointer to the newly created object on the heap

•      The only way to access data on the heap is with pointers, since the only handle you have is the address where it is located

Example

int main( )
{
    string *strPtr;

    strPtr = new string( "hello" );
   
cout << "The string is: " << *strPtr << endl;
    cout << "Its length is: " << (*strPtr).length( )
            
<< endl; 
// note the parententheses;  the dot operator has higher precedence than the * operator

    *strPtr += " world";
    cout << "Now the string is " << *strPtr << endl;

    delete strPtr;

    return 0;
}

 

 

Garbage collection

•      In Java, all space allocated on the heap is automatically returned to the OS when it is no longer needed: 

–   this is garbage collection

•      C++ has no garbage collection; it is up to the programmer to return unused space on the heap to the OS so it can be used again

–   Memory leaks occur if this is not done.

The delete operator

•      When an object that has been allocated by new is no longer referenced, the programmer must return the space to the OS.

•      This is done using the delete operator

–   Otherwise the memory it used is lost until the program terminates.

•      The delete operator is applied to the object through a pointer
   
delete strPtr;

–    the pointer itself still exists, but the memory it is pointing to can now be reused by the operating system

 

Stale pointers

•      A stale pointer points to address space on the heap that has been returned to the operating system by delete.

•      Sometimes this space will have been reused by the OS, and sometimes it may not have.

–   Since this varies, it is a very hard bug to find.

•      The way this usually happens is by having more than one pointer to an object (common in C++)

 

Using pointers for linked lists

•      Keeping list is one thing computers do all the time

•      There are several ways to store lists on the computer

–   In a text file

–   In arrays or vectors

–   In linked lists

–   In binary search trees (always keep the list sorted)

 

Using arrays to store lists

•      There are advantages and disadvantages to storing lists this way

–   Advantages

•   Arrays are random access; if you know the index, you can go directly to an item in the array

•   It is fast to add items to the end of the list

–   Disadvantages

•   If you wan to add an item to the front of the list, or the middle, all the items behind must be shifted

•   Arrays must be stored contiguously in RAM, so the size must be known when the array is put into RAM.

–   Even a vector must be reallocated when it gets too big

 

Using linked lists to store lists

•      The space for a linked list is allocated dynamically, as a program runs

•      The head of the list is a pointer, which is stored on the runtime stack.

•      Each item in the list is kept in a node, which is a two part object

–   One part is of the type to be kept in the list

–   The other part is a pointer, which points to the next item in the list.

 

Advantages and disadvantages of linked lists

•      They allow you to insert items anywhere in the  list by just changing pointers

–   No data moving

•      They are stored non contiguously, so they can grow to any size

•      They do not allow random access, the list must be traversed to find an item.