PowerPoint Slides for Starting Out With C++ Eearly Objects ... · C++ automatically stores the...
Transcript of PowerPoint Slides for Starting Out With C++ Eearly Objects ... · C++ automatically stores the...
Chapter 09
Pointers
Fall 2020The Borough of Manhattan
Community College
Getting the Address of a Variable
•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 = -99;
cout << # // prints address
// in hexadecimal
Pointer Variables
•Pointer variable: Often just called a pointer, it’s a
variable that holds an address
•Because a pointer variable holds the address of
another piece of data, it "points" to the data
•Pointer variables are another way using a
memory address to work with a piece of data
(alternate way to access memory locations)
Something Like Pointers: Arrays
•We have already worked with something similar to pointers, when we learned to pass arrays as arguments to functions
•For example, suppose we use this statement to pass the array numbers to the showValuesfunction:
showValues(numbers, SIZE);
Something Like Pointers: Arrays
The values parameter, in the showValues function, points to the numbers
array.
C++ automatically stores the address of numbers in the values parameter.
Something Like Pointers: Reference Variables
• We have also worked with something like pointers when we learned to use reference variables. Suppose we have this function:
void getOrder(int &donuts)
{
cout << "How many doughnuts do you want? ";
cin >> donuts;
}
• And we call it with this code:
int jellyDonuts;
getOrder(jellyDonuts);
Something Like Pointers: Reference Variables
The donuts parameter, in the getOrder function, points to the
jellyDonuts variable.
C++ automatically stores the address of jellyDonuts in the donuts
parameter.
Pointer Variables
•Definition:int *intptr;
Read as:“intptr can hold the address of an int” or
“intptr is a pointer to an int”
•Spacing in definition does not matter:
int * intptr; // same as above
int* intptr; // same as above
•* is called the indirection operator
Pointer Variables
•Definition and assignment:int num = 25;int *intptr;intptr = #
•Memory layout:
•You can initialize pointer variables with the special value nullptr
A Pointer Variable in Program 9-2
The Indirection Operator
•The indirection operator (*) dereferences a
pointer
•It allows you to access the item that the
pointer points to
int x = 25;
int *intptr = &x;
cout << *intptr << endl;
This prints 25
The Indirection Operator in Program 9-3
The Indirection Operator in Program 9-3
The Relationship Between Arrays and
Pointers
An array name is the starting address of the array
int vals[] = {4, 7, 11};
cout << vals; // displays 0x4a00
cout << vals[0]; // displays 4
cout << &vals[0]; // displays 0x4a00
cout << &vals[1]; // displays 0x4a04
•An array name can be used as a constant pointer
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
The Relationship Between Arrays and
Pointers
The Array Name Being Dereferenced in Program 9-5
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; // displays 4
cout << *(valptr+1); // displays 7
cout << *(valptr+2); // displays 11
Must use ( ) in expressions
Array Access
•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;
Array Access
•Array notation
vals[i]
is equivalent to the pointer notation
*(vals + i)
•No bounds checking performed on array
access, whether using array name or a pointer
with a subscript to access the array
From Program 9-7
Pointer Arithmetic
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 -
Pointer Arithmetic
• Operations on pointer variables:
Operation Example
int vals[]={4,7,11};
int *valptr = vals;
++, -- valptr++; // points at 7
valptr--; // now points at 4
+, - (pointer and int) cout << *(valptr + 2); // 11
+=, -= (pointer and int) valptr = vals; // points at 4
valptr += 2; // points at 11
- (pointer from pointer) cout << valptr – vals; // prints 2
// (number of ints) between valptr
// and vals
From Program 9-9
Initializing Pointers
•You can initialize to NULL, nullptr, or 0 (zero)
int *ptr = nullptr;
•You can initialize to addresses of other variables
int num, *numPtr = #
int val[3], *valptr = val;
•The initial value must have the correct type
double cost;
int *ptr = &cost; // won't work
Checkpoint
What is the output of the following program?
#include <iostream>using namespace std;int main(){
int x = 50, y = 60, z = 70;int *ptr;
ptr = &x; *ptr *= 5; ptr = &y; *ptr *= 10; ptr = &z; *ptr *= 2; cout << x << " " << y << " " << z << endl;return 0;
} 250 600 140
Comparing Pointers
•Relational operators (<, >=, etc.) 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
Comparing Pointers
• If one address comes before another address in memory, the first address is considered “less than” the second
• In an array, all the elements are stored in consecutive memory locations, so the address of element 1 is greater than the address of element 0
• A pointer can be a parameter. It works like a reference parameter to allow changes to argument from within a function
Requires:
1) asterisk * on parameter in prototype and header
void getNum(int *); //prototype
void getNum(int *ptr) //header
2) asterisk * in function body to dereference the pointer
cin >> *ptr;
3) pointer or address as argument to the function in the call
getNum(numPtr); //or
getNum(&num);
Pointers as Function Parameters
Pointers as Function Parameters
void swap(int *x, int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
int num1 = 2, num2 = -3;
swap(&num1, &num2); //call
(Program Continues)
Pointers as Function Parameters in Program 9-11
Pointers as Function Parameters in Program 9-11
Pointers to Constants
•A pointer to a constant: you cannot change
the value that is pointed at
const double *rates;
Constant Pointers
•A constant pointer is a pointer that is initialized
with an address, and cannot point to anything else
int value = 24;
int * const ptr = &value;
Constant Pointers to Constants
•A constant pointer to a constant is:
–a pointer that points to a constant
–a pointer that cannot point to anything except what it is pointing to
•Example:const int value = 22;
const int * const ptr = &value;
Constant Pointers to Constants
Dynamic Memory Allocation
•You can allocate storage for a variable while
a program is running
•Use the new operator to allocate memory
double *ptr;
ptr = new double;
•new returns address of a memory location
Dynamic Memory Allocation
int *iptr;
iptr = new int;
*iptr = 25;
cout << *iptr; // displays 25
cin >> *iptr; // let the user input a value
total += *iptr; // uses the memory content in a // computation
Dynamic Memory Allocation
• Can also use new to allocate array:arrayPtr = new double[25];
• Can then use [] or pointer arithmetic to access array:for(i = 0; i < 25; i++)
arrayptr[i] = i * i;
or
for(i = 0; i < 25; i++)
*(arrayptr + i) = i * i;
• Program will terminate if not enough memory available to allocate
Dynamic Memory Example
int x;
int *arrayPtr;
cout <<"How many students? ";
cin >> x;
arrayPtr = new int[x];
for (int i = 0; i < x; i++)
{
cout << "Enter score " << i + 1 << ": ";
cin >> arrayPtr[i];
}
Releasing Dynamic Memory
•Use delete to free dynamic memory
delete intPtr;
•Use delete [] to free dynamic array memory
delete [] arrayPtr;
•Only use delete with dynamic memory!
Memory Leaks and Dangling Pointers
•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
•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 nullptr as soon as the
memory is freed
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
Memory Leaks
Program 9-14 (Continued)
Dynamic Memory Allocation in Program 9-14
Dynamic Memory Allocation in Program 9-14
Program 9-14 (Continued)
Dynamic Memory Allocation in Program 9-14Program 9-14 (Continued)
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, or
–to dynamically allocated memory
Returning Pointers from Functions
int* squares(int n)
{
// Allocate an array of size n
int *arrayPtr = new int[n];
// Fill the array with squares
for (int k = 0; k < n; k++)
arrayPtr[k] = (k+1) * (k+1);
// Return base address of allocated array
return arrayPtr;
}
int *ptr = squares(5); //call
Pointers to Structures and Class Objects
•You can create pointers to objects and structure
variables
struct Student {…};
class Square {…};
Student stu1;
Student *stuPtr = &stu1;
Square sq1;
Square *sqrPtr = &sq1;
•You need to use() when using * and . operators
(*stuPtr).studentID = 12204;
Structure Pointer Operator ‒>
•The simpler form ptr->member can be used in place of the form (*ptr).member
- Instead of
(*stuPtr).studentID = 12204; //and
(*sqrPtr).setSide(14);
- Use
stuPtr->studentID = 12204; //and
sqrPtr->setSide(14);
Dynamic Memory with Objects
•You can allocate dynamic structure variables and
objects using pointers:
sqrPtr = new Square;
sqrPtr->setSide(20);
•You can simultaneously allocate the object and
invoke the constructor:
sqrPtr = new Square(20);
• delete causes destructor to be invoked:
delete sqrPtr;
Selecting Members of Objects
•Situation: A structure/object contains a pointer as
a member. There is also a pointer to the
structure/object
struct Course
{ string courseNum;
int *creditsPtr;
}
•Problem: How do we access the pointer member
via the structure/object pointer?
Selecting Members of Objects
struct Course
{ string courseNum;
int *creditsPtr;
}
Course test1, *testPtr = &test1;
Expression Meaning .
testPtr->creditsPtr Access the credits pointer in test1.
This is the same as (*testPtr).creditsPtr
*testPtr->creditsPtr Access the value pointed at by
testPtr->creditsPtr
*test1.creditsPtr Access the value pointed at by
test1.creditsPtr
Using Smart Pointers to Avoid Memory Leaks
• In C++ 11, you can use smart pointers to dynamically
allocate memory and not worry about deleting the
memory when you are finished using it
• Three types of smart pointer:unique_ptr
shared_ptr
weak_ptr
• In this book, we introduce unique_ptr:
unique_ptr<int> ptr( new int );
• Must #include the memory header file:
#include <memory>
• The notation <int> indicates that the pointer can point to an int
• The name of the pointer is ptr
• The expression new int allocates a chunk of memory to hold an
int
• The address of the chunk of memory will be assigned to ptr
Using Smart Pointers to Avoid Memory Leaks
Using Smart Pointers in Program 9-17
Using Smart Pointers to Avoid Memory Leaks
• Smart pointers can be used to dynamically allocate arrays:
unique_ptr<int[]> ptr(new int[100]);
• You can define an uninitialized unique_ptr, then assign
it a value in a later statement:
unique_ptr<int> ptr;
ptr = unique_ptr<int>(new int);
• Smart pointers support the same * and -> deferencing
operators as regular pointers, but do not support pointer
arithmetic:
ptr++; // ERROR!