powerpoint slides for starting out with c++ eearly objects ... · c++ automatically stores the...

Post on 11-Nov-2020

4 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

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 << &num; // 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 = &num;

•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 = &num;

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!

top related