1 of 48

CNSP - Lecture 10� Chapter 10

BY PROF. RAFAEL ORTA

Disclosure: this presentation includes slides that were provided by the textbook publisher and Dr. Hnatyshin, some are adaptation, and some are an exact replica.

2 of 48

Last week we covered

9.1  Introduction to Search Algorithms

9.2  Searching an Array of Objects

9.3  Introduction to Sorting Algorithms

9.4  Sorting an Array of Objects

9.5  Sorting and Searching Vectors

9.6  Introduction to Analysis of Algorithms

3 of 48

This week we will cover

10.1 Pointers and the Address Operator

10.2 Pointer Variables

10.3 The Relationship Between Arrays

and Pointers

10.4 Pointer Arithmetic

10.5 Initializing Pointers

10.6 Comparing Pointers

10.7 Pointers as Function Parameters

10.8 Pointers to Constants and Constant Pointers

10.9 Dynamic Memory Allocation

10.10 Returning Pointers from Functions

4 of 48

How do you call individual components of a struct?

5 of 48

A/ Members

6 of 48

10.1 Pointers and the Address Operator

  • Each variable in a program is stored at a unique location in memory that has an address
  • Use the address operator & to get the address of a variable:

int num = -23;

cout << &num; // prints address

// in hexadecimal

  • The variable contains the address of a memory location is a pointer

7 of 48

10.2 Pointer Variables 1 of 3

  • Pointer variable (pointer): a variable that holds an address
  • Pointers provide an alternate way to access memory locations

8 of 48

Pointer Variables 2 of 3

  • Definition:

int *intptr;

  • Read as:

intptr can hold the address of an int” or “intptr is a pointer to an int

  • The spacing in the definition does not matter:

int * intptr;

int* intptr;

  • * is called the indirection or dereferencial operator

9 of 48

Pointer Variables 3 of 3

  • Definition and assignment:

int num = 25;

int *intptr;

intptr = &num;

  • Memory layout:

  • You can access num using intptr and indirection operator *:

cout << intptr; // prints 0x4a00

cout << *intptr; // prints 25

*intptr = 20; // puts 20 in num

10 of 48

11 of 48

10.3 The Relationship Between Arrays �and Pointers 1 of 2

An array name is the starting address of the array

int vals[] = {4, 7, 11};

cout << vals; // displays 0x4a00

cout << vals[0]; // displays 4

12 of 48

The Relationship Between Arrays and �Pointers 2 of 2

  • An array name can be used as a pointer constant

int vals[] = {4, 7, 11};

cout << *vals; // displays 4

  • A pointer can be used as an array name

int *valptr = vals;

cout << valptr[1]; // displays 7

13 of 48

Pointers in Expressions

  • Given:

int vals[]={4,7,11};

int *valptr = vals;

  • What is valptr + 1?
  • It means (address in valptr) + (1 * size of an int)

cout << *(valptr+1); // displays 7

cout << *(valptr+2); // displays 11

  • Must use ( ) in expression

14 of 48

Array Access 1 of 2

Array elements can be accessed in many ways

Array access method

Example

array name and [ ]

vals[2] = 17;

pointer to array and [ ]

valptr[2] = 17;

array name and subscript arithmetic

*(vals+2) = 17;

pointer to array and subscript arithmetic

*(valptr+2) = 17;

15 of 48

Array Access 2 of 2

  • Array notation

vals[i]

is equivalent to the pointer notation

*(vals + i)

  • Remember that no bounds checking is performed on array access. This applies to using a pointer for access as well as using the array name and a subscript.

16 of 48

10.4 Pointer Arithmetic 1 of 5

Some arithmetic operators can be used with pointers:

    • Increment and decrement operators ++, --
    • Integers can be added to or subtracted from pointers using the operators +, -, +=, and -=
    • One pointer can be subtracted from another by using the subtraction operator -

17 of 48

Pointer Arithmetic 2 of 5

Assume the variable definitions

int vals[]={4,7,11};

int *valptr = vals;

Examples of use of ++ and --

valptr++; // points at 7

valptr--; // now points at 4

18 of 48

Pointer Arithmetic 3 of 5

Assume the variable definitions:

int vals[]={4,7,11};

int *valptr = vals;

Example of the use of + to add an int to a pointer:

cout << *(valptr + 2)

This statement will print 11

19 of 48

Pointer Arithmetic 4 of 5

Assume the variable definitions:

int vals[]={4,7,11};

int *valptr = vals;

Example of use of +=:

valptr = vals; // points at 4

valptr += 2; // points at 11

20 of 48

Pointer Arithmetic 5 of 5

Assume the variable definitions

int vals[] = {4,7,11};

int *valptr = vals;

Example of pointer subtraction

valptr += 2;

cout << valptr - val;

This statement prints 2: the number of

ints between valptr and val

21 of 48

22 of 48

10.5 Initializing Pointers

  • You can initialize to NULL or 0 (zero)

int *ptr = NULL;

  • You can initialize to addresses of other variables

int num, *numPtr = &num;

int val[ISIZE], *valptr = val;

  • The initial value must have the correct type

float cost;

int *ptr = &cost; // won't work

23 of 48

Initializing Values in C++ 11

  • In C++ 11, putting empty { } after a variable definition indicates that the variable should be initialized to its default value
  • C++ 11 also has the the key word nullptr to indicate that a pointer variable does not contain a valid memory location
  • You can use

int *ptr = nullptr;

  • or

int *ptr{ };

24 of 48

25 of 48

10.6 Comparing Pointers

  • Relational operators can be used to compare the addresses in pointers
  • Comparing addresses in pointers is not the same as comparing contents pointed at by pointers:

if (ptr1 == ptr2) // compares

// addresses

if (*ptr1 == *ptr2) // compares

// contents

26 of 48

10.7 Pointers as Function Parameters 1 of 3

  • A pointer can be a parameter
  • It works like a reference parameter to allow changes to argument from within a function
  • A pointer parameter must be explicitly dereferenced to access the contents at that address

27 of 48

Pointers as Function Parameters 2 of 3

Requires:

1) asterisk * on parameter in prototype and

header

void getNum(int *ptr);

2) asterisk * in body to dereference the pointer

cin >> *ptr;

3) address as argument to the function in the call

getNum(&num);

28 of 48

Pointers as Function Parameters 3 of 3

void swap(int *x, int *y)

{

int temp;

temp = *x;

*x = *y;

*y = temp;

}

int num1 = 2, num2 = -3;

swap(&num1, &num2); //call

29 of 48

Passing an Array Via a Pointer �Parameter

  • A pointer parameter receives an address when a function is called

  • The address could be for a single variable, or it could be the address of the first element of an array.

  • You can use either subscript notation or pointer arithmetic to access the elements of the array.

30 of 48

31 of 48

10.8 Pointers to Constants and Constant Pointers

  • A pointer to a constant: you cannot change the value that is pointed at
  • A constant pointer: the address in the pointer cannot be changed after the pointer is initialized

32 of 48

Pointers to Constants

  • Must use the const keyword in the pointer definition:

const double taxRates[] =

{0.65, 0.8, 0.75};

const double *ratePtr;

  • Use the const keyword for pointer parameters in function headers to protect data from modification in the function, as well as to pass addresses of const arguments

33 of 48

Pointer to Constant – What does the Definition Mean?

Read as: “rates is a pointer to a constant that is a double.”

34 of 48

Constant Pointers

  • A constant pointer is a pointer whose data (the address in the pointer) cannot change
  • Defined with the const keyword next to the variable name:

int classSize = 24;

int * const classPtr = &classSize;

  • It must be initialized when defined
  • No initialization needed if used as a function parameter
    • Initialized by the argument when function is called
    • Arguments can differ on different function calls
  • While the address in the pointer cannot change, the data at that address may be changed

35 of 48

Constant Pointer – What does the Definition Mean?

Read as: “ptr is a constant pointer to an int.”

36 of 48

Constant Pointer to Constant

  • You can combine pointers to constants and constant pointers:

int size = 10;

const int * const ptr = &size;

  • What does it mean?

37 of 48

38 of 48

39 of 48

10.9 Dynamic Memory Allocation 1 of 2

  • You can allocate storage for a variable while a program is running
  • Use the new operator to allocate memory

double *dptr;

dptr = new double;

  • new returns address of a memory location
  • The data type of the variable is indicated after new

40 of 48

Dynamic Memory Allocation 2 of 2

  • You can also use new to allocate an array

arrayPtr = new double[25];

    • The program may terminate if there is not sufficient memory

  • You can then use [ ] or pointer arithmetic to access the array

41 of 48

Dynamic Memory Example

int *count, *arrayptr;

count = new int;

cout <<"How many students? ";

cin >> *count;

arrayptr = new int[*count];

for (int i=0; i<*count; i++)

{

cout << "Enter score " << i << ": ";

cin >> arrayptr[i];

}

42 of 48

Releasing Dynamic Memory

  • Use delete to free dynamic memory

delete count;

  • Use delete [] to free dynamic array memory

delete [] arrayptr;

  • Only use delete with dynamic memory!

43 of 48

44 of 48

Dangling Pointers and Memory Leaks

  • A pointer is dangling if it contains the address of memory that has been freed by a call to delete.
    • Solution: set such pointers to NULL (or nullptr in C++ 11) as soon as the memory is freed.
  • A memory leak occurs if no-longer-needed dynamic memory is not freed. The memory is unavailable for reuse within the program.
    • Solution: free up dynamic memory after use

45 of 48

10.10 Returning Pointers from Functions

  • A pointer can be the return type of function

int* newNum();

  • The function must not return a pointer to a local variable in the function
  • The function should only return a pointer
    • to data that was passed to the function as an argument
    • to dynamically allocated memory

46 of 48

More on Memory Leaks

General guidelines to avoid memory leaks:

  • If a function allocates memory via new, it should, whenever possible, also deallocate the memory using delete
  • If a class needs dynamic memory, it should
    • allocate it using new in the constructor
    • deallocate it using delete in the destructor

47 of 48

48 of 48