## Chapter 10: Pointers

## Chapter Goals

- To learn how to declare, initialize and use pointers
- To become familiar with dynamic memory allocation and deallocation
- To use pointers in common programming situations that involve optional and shared objects
- To understand the relationship between arrays and pointers
- To be able to convert between string objects and character pointers

## Pointers and Memory Allocation

- The C++ run-time system can create new objects for us.
- When we create a new object, a memory alllocator finds a storage location for the object.
- The memory allocator keeps a large storage area, called the heap, for that purpose.
- The heap is a flexible pool of memory that can hold values of any type.
- When you allocate a new heap object, the memory allocator tells where the object is located, by giving you the object's memory address.
- To manipulate memory addresses, you need to use a pointer.

## Pointers and Memory Allocation (Syntax 10.1 `new` Expression)

Syntax 10.1 : `new` Expression
    new type_name
    new type_name(exprssion1, expression2, . . . , expressionn)
Example: |
    new Time;
    new Employee("Lin, Lisa", 68000)
Purpose: | Allocate and construct a value on the heap and return a pointer to the value.

## Pointers and Memory Allocation (Syntax 10.1 Pointer Variable Definition)

Syntax 10.2 : Pointer Variable Definition
    type_name* variable_name;
    type_name* variable_name = expression;
Example: |
    Employee* boss;
    Product* p = new Product;
Purpose: | Define a new pointer variable, and optionally supply an initial value.

## Pointers and Memory Allocation

- Pointers are declared by placing an`*` after the typename.

  >     Time * deadline;

- Pointers hold the location of an object, not the actual object itself.
- To create a new object, you use the `new` command.

  >     deadline = new Time;

- You can also call the `new` command in conjunction with a constructor to initialize the object.

  >     Employee* boss = new Employee("Lin, Lisa", 68000);

- To access the object that a pointer points to, the object must be dereferenced:
  - Use `*` to access the actual object.
  - Use `->` to access methods of the object.

  >     raise_salary(*boss, 10);
  >     string name = boss->get_name();

- The dot operator has a higher precedence than the `*` operator:

  >     string name = *boss.get_name(); // Error
  >     string name = (*boss).get_name(); // OK

## Pointers and Memory Allocation (Syntax 10.3 Pointer Dereferencing)

Syntax 10.3 : Pointer Dereferencing
    *pointer_expression
    pointer_expression->class_member
Example: |
    *boss
    boss->set_salary(70000)
Purpose: | Access the object to which a pointer points.

## Pointers and Memory Allocation

- The special value `NULL` indicates that a pointer doesn't point anywhere.
- Instead of leaving pointers uninitialized, you should always set them to `NULL` when you define them.

  >     Employee* boss = NULL; // will set later
  >     . . .
  >     if (boss != NULL) name = boss->get_name(); // OK

- You cannot dereference a `NULL` pointer.

  >     Employee* boss = NULL;
  >     string name = boss->get_name(); // NO!! Program will crash

## Deallocating Dynamic Memory

- When you make a variable of a certain type, the object is allocated on the run-time stack. This object automatically goes away when the program leaves the block in which the variable is allocated:

  >     void f()
  >     {
  >        Employee harry; // memory for employee allocated on the stack
  >        . . .

  >     } // memory for employee object automatically reclaimed

- Value that are allocated on the heap do not follow this automatic allocation mechanism. You must reclaim the memory using the `delete` operator.

  >     void g()
  >     {
  >        Employee* boss;
  >        boss = new Employee(. . .);
  >           // memory for employee object allocated on the heap
  >        . . .
  >        delete boss; // memory for employee object manually reclaimed
  >     } // memory for boss automatically reclaimed

## Deallocating Dynamic Memory (Syntax 10.4 `delete` Expression)

Syntax 10.4: `delete` Expression
    delete pointer_expression
Example: |
    delete boss;
Purpose: | Deallocate a value that is stored on the heap and allow the memory to be reallocated.

## Deallocating Dynamic Memory

- Reclaiming a pointer variable does not automatically reclaim the object to which it points.
- (Common Error 10.4) A memory block that is not deallocated is called a memory leak.
- Leaked memory can cause the heap to run out of memory.
  - Program crashes.
  - Computer freezes up.
- When a pointer is defined it points to a random address; using this random address causes and error.

  >     Employee* boss;
  >     string name = boss->get_name(); // NO!! boss contains a random address

- After you `delete` the value attached to a pointer, you can no longer use that address.

  >     delete boss;
  >     string name = boss->get_name(); // NO!! boss points to a deleted element

- (Common Error 10.3) Such pointers are called dangling because they do not point to a valid object.

## Common Uses for Pointers (Optional Attributes)

- One use for pointers is optional attributes.
- If the attribute is needed, the pointer is set to the address of the object; otherwise the pointer will be set to `NULL`.

  >     class Department
  >     {
  >      . . .
  >     private:
  >        string name;
  >        Employee* receptionist;
  >     };

- This is better than allocating space for an object that might not be used.

  >     class Department // modeled without pointer
  >     {
  >      . . .
  >     private:
  >        string name;
  >        bool has_receptionist;
  >        Employee receptionist;
  >     };

## Common Uses for Pointers (Sharing)

- Another common use of pointers is sharing.
- Rather than duplicating objects, we can use pointers to share the object.
- Pointers are useful to model a "n:1" relationship, in which a number of different variables share the same object.
- Example: Many departments may have a receptionist and a secretary. In some departments, this it the same person.

  >     class Department
  >     {
  >      . . .
  >     private:
  >        string name;
  >        Employee* receptionist;
  >        Employee* secretary;
  >     };

- Sharing is particularly important when changes to the object need to be observed by all users of the object.

  >     Employee* tina = new Employee("Tester, Tina", 50000);
  >     Department qc("Quality Control");
  >     qc.set_receptionist(tina);
  >     qc.set_secretary(tina);
  >     tina->set_salary(55000);

- Without using pointers, changing Tina's salary would not update the information in the receptionist or secretary attribute.

## Common Uses for Pointers (`department.cpp`)

## Arrays and Pointers

- There is an intimate connection between arrays and pointers in C++.
- The name of an array is a pointer to the starting element.

  >     int a[10];
  >     int* p = a; // now p points to a[0];
  >     *a = 12; // same as a[0] = 12;

- You can add an integer to offset to the pointer to point to another array location (pointer arithmetic).

  >     *(a + 3) means the same as a[3]

- This relationship is called the array/pointer duality law. For any integer `n`,

  >     *(a + n) means the same as a[n]

## Arrays and Pointers

- When an array is passed into a function, it is actually a pointer to the starting element of the array.

  >     double maximum(const double a[], int a_size)
  >     {
  >        if (a_size == 0) return 0;
  >        double highest = a[0];
  >        int i;
  >        for (i = 0; i < a_size; i++)
  >           if (a[i] > highest)
  >              highest = a[i];
  >        return highest;
  >     }

- The declaration gives the illusion that an entire array is passed to the function, but in fact the function receives only the starting address of the array.

  >     double maximum(const double* a, int a_size)
  >     {
  >        /* identical code as above yields same results */
  >        . . .
  >     }

- It is essential that the function also knows where the array ends.

## Pointers to Character Strings

- C++ inherits a more primitive level of string handling from the C language, in which strings are represented as arrays of `char` values.
- We don't recommend that you use character pointers or arrays in your programs, but you occasionally need to interface with functions that receive or return `char*` values.

  >     char s[] = "Harry";

  > `s[0]` | `s[1]` | `s[2]` | `s[3]` | `s[4]` | `s[5]`
  > `'H'` | `'a'` | `'r'` | `'r'` | `'y'` | `'\0'`

- Literal strings are stored inside `char` arrays.

## Pointers to Character Strings

- The `string` class has a constructor `string(char *)` that you can use to convert any character pointer or array to a safe an convenient `string` object.

  >     char* p = "Harry";
  >     string name(p);

- Use the `c_str` member function of the `string` class to obtain a `char*` pointer that points to the first character in the `string` object.
- The `tempnam` function in the standard library yields the name of a temporary file, and expects a `char*` parameter for the directory name.

  >     string dir = . . .;
  >     char* p = tempnam(dir.c_str(), NULL);
  >     string file_name(p);