Arrays and Pointers Joe Meehean. Arrays What if we want to store multiple items? e.g., points scored...

105
Arrays and Pointers Joe Meehean

Transcript of Arrays and Pointers Joe Meehean. Arrays What if we want to store multiple items? e.g., points scored...

Arrays and Pointers

Joe Meehean

Arrays• What if we want to store multiple items?• e.g., points scored for each of the 16 regular season Packer

games• e.g., miles traveled each day on a 3 day journey

• Arrays• store a collection of items of the same data type• items are stored in a specific order• individual items are not named• referenced by position in array (1st item, 2nd item, etc…)• arrays are fixed size, they cannot grow or shrink• C++ arrays do not store the size of the array

2

Arrays• Compound data type: type name[dimension]• type: specifies data type of items stored in array• name is the name of the array variable• dimension: determines size of the array (# of elements)• e.g., int array[10];• e.g., char alphabet[26];• e.g., float student_gpas[15];

• dimension must be a constant unsigned expression• defined at compile time• e.g., int array[10];• constant variables are allowed (more on this later)

3

Arrays• Explicitly initializing arrays• comma separated list of values for items in array• enclosed in curly braces• e.g., int a[3] = {5, 6, 7}• e.g., int a[] = {5, 6, 7}

• If array items are not initialized at creation• and the data type is a built-in (e.g., int, float, char, etc…)• and the array is defined outside of a function,

then elements are initialized to 0• and the array is defined inside of a function,

then elements are left unitialized

4

Arrays• What happens when you create an array• allocates a contiguous block of memory• enough to store dimension items• initializes the memory

5

// outside of a functionint odds[5];

00000

odds

Arrays• Accessing array elements• Uses [] operator• Index starts at 0• for an array of 10 elements• indices range from 0 to 9

6

int odds[5];…// prints 1st elementcout << odds[0] << endl;

// prints 5th elementcout << odds[4] << endl;

00000

0

1

2

3

4

odds

Arrays• Assigning array elements• Also uses [] operator• Index also starts at 0

7

int odds[5];…// assigns 1st elementodds[0] = 1;

// assigns 5th elementodds[4] = 9;

10009

0

1

2

3

4

odds

Arrays• Accessing and assigning array elements using variables• index variable should a size_t type• treat it like an unsigned integer

8

int odds[5];// assign odd numberssize_t index;for(index = 0; index < 5; index++){

odds[index] = index * 2 + 1;}

// prints all of the elementsfor(index = 0; index < 5; index++){

cout << odds[index] << endl;}

13579

0

1

2

3

4

odds

Arrays• Illegal operations• using the copy operation: int array1(array2)• or the assignment operation: array1 = array2

• Dangerous operations, but legal• arrays won’t prevent you from accessing memory outside of what

you allocated• accesses or modifies other variables that are stored near it

• really bad news• e.g.,int odds[5];cout << odds[-1] << endl;cout << odds[5] << endl;

9

Arraysint counter = 15;int odds[5];int other = 12

10

13579

0

1

2

3

4

odds

other: 12

counter: 15

Arraysint counter = 15;int odds[5];int other = 12odds[-1] = -1;odds[5] = 11;

11

13579

0

1

2

3

4

odds

other: 11

counter: -1

Arrays

• Problems with this code• Readability • what is 5? what does 5 mean?• magic number

• Maintainability• what if we need to keep the first 10 odds• 80% of 5’s in code refer to odds array size, others do not• how can we tell which is which

12

int odds[5];…// prints all of the elementssize_t index;for(index = 0; index < 5; index++){

cout << odds[index] << endl;}

Arrays

• replace 5 with variable name MAX_ODDS• increases readability• easy to change size of odds array• problem: dimension must be a constant literal• e.g., 5, 18, 98

• or it must be a constant variable13

int MAX_ODDS = 5;int odds[MAX_ODDS];…// prints all of the elementssize_t index;for(index = 0; index < MAX_ODDS; index++){

cout << odds[index] << endl;}

Constant Variables• Use the const keyword• makes the variable constant• assigned its value during compilation• cannot be changed after its initialization

• e.g., const int MAX_ODDS = 5;int odds[MAX_ODDS];

• Trying to overwrite MAX_ODDS now results in compiler error• e.g., MAX_ODDS = 15; // compiler error

14

Questions?

15

• Create two arrays of size 10• fill the 1st with the 1st 10 odd numbers• fill the 2nd with the 1st 10 even numbers

• Write a function to print the contents of an integer array• the function should take the array as a parameter

• Write a function to copy the values from one array to another

16

PRACTICE!!!

Aliasing• An alias is another name for the same object• two variables names are attached to the same data

• Aliasing is really important in C++• and many other programming languages• well see why when we cover Objects

• C++ does aliasing in two ways• references• pointers

17

References• References are aliases that “refer” to other variables• its just another name for an object

• Compound type• type defined in terms of another type• e.g., arrays are compound types

• Reference is a compound type• type &variable;• e.g., int &foo;• should be read from right to left:

“foo is a reference to an int”

18

References• Initializing a reference• References must be initialized at declaration• Must be initialized using object of the same type• cannot be initialized using a literal

• After initialization a reference is forever bound to that object• cannot rebind to another object

19

int val = 7;int &refVal = val; // GOODint &refVal2; // ERRORint &refVal3 = 11; // ERRORdouble dval = 2.1;int &refVal3 = dval; // ERROR

References• All operations on a reference are performed on the

underlying object

20

int val = 7;int &refVal = val;

7val

refVal

refVal = 9; 9val

refVal

val++; 10val

refVal

References• References to constants• cannot change the underlying data• can refer to a const object or even literals• created using const keyword

21

const int val = 7;const int &refVal = val; // GOOD

int &refVal2 = val; // ERROR

const int &refVal3 = 11; // GOOD

const int &refVal4 = 12 * 57 + 1; // GOOD

References• As parameters of a function• nonreference parameters are copied using the

corresponding function arguments• the original arguments cannot be changed

22

int arg1 = 7;int arg2 = 15;swap(arg1, arg2);

void swap(int parm1, int parm2){ int tmp = parm1; parm1 = parm2; parm2 = tmp;}

7arg1

15arg2

References• As parameters of a function• nonreference parameters are copied using the

corresponding function arguments• the original arguments cannot be changed

23

int arg1 = 7;int arg2 = 15;swap(arg1, arg2);

void swap(int parm1, int parm2){ int tmp = parm1; parm1 = parm2; parm2 = tmp;}

7arg1

15arg2

7parm1

15parm2

References• As parameters of a function• nonreference parameters are copied using the

corresponding function arguments• the original arguments cannot be changed

24

int arg1 = 7;int arg2 = 15;swap(arg1, arg2);

void swap(int parm1, int parm2){ int tmp = parm1; parm1 = parm2; parm2 = tmp;}

7arg1

15arg2

7 15parm1

15 7parm2

References• As parameters of a function• nonreference parameters are copied using the

corresponding function arguments• the original arguments cannot be changed

25

int arg1 = 7;int arg2 = 15;swap(arg1, arg2);

void swap(int parm1, int parm2){ int tmp = parm1; parm1 = parm2; parm2 = tmp;}

7arg1

15arg2

References• As parameters of a function• reference parameters only copy the reference,

not the actual data• binds parameters to argument’s data

26

int arg1 = 7;int arg2 = 15;swap(arg1, arg2);

void swap(int& parm1,int& parm2){ int tmp = parm1; parm1 = parm2; parm2 = tmp;}

7arg1

15arg2

References• As parameters of a function• reference parameters only copy the reference,

not the actual data• binds parameters to argument’s data

27

int arg1 = 7;int arg2 = 15;swap(arg1, arg2);

void swap(int& parm1,int& parm2){ int tmp = parm1; parm1 = parm2; parm2 = tmp;}

7arg1

15arg2

parm2

parm1

References• As parameters of a function• reference parameters only copy the reference,

not the actual data• binds parameters to argument’s data

28

int arg1 = 7;int arg2 = 15;swap(arg1, arg2);

void swap(int& parm1,int& parm2){ int tmp = parm1; parm1 = parm2; parm2 = tmp;}

7 15arg1

15 7arg2

parm2

parm1

References• As parameters of a function• reference parameters only copy the reference,

not the actual data• binds parameters to argument’s data

29

int arg1 = 7;int arg2 = 15;swap(arg1, arg2);

void swap(int& parm1,int& parm2){ int tmp = parm1; parm1 = parm2; parm2 = tmp;}

7 15arg1

15 7arg2

References• Passing references avoids expensive copies• Adds new problems that data may be changed• maybe we want to be sure it won’t be• or want to use literals without copying

• Pass const references

30

bool isNegative(int& parm1){ return (parm1 < 0 );}

int val = -7;isNegative(val); // OKisNegative(-15); // WON’T COMPILE

References• Passing references avoids expensive copies• Adds new problems that data may be changed• maybe we want to be sure it won’t be• or want to use literals without copying

• Pass const references

31

bool isNegative(const int& parm1){ return (parm1 < 0 );}

int val = -7;isNegative(val); // OKisNegative(-15); // OK

References• Returning nonreferences• the return value (object) is copied• e.g., add 1 to absolute value

32

int arg = -4;abs(arg)++;cout << arg << endl;

int abs(int& parm){ if( parm < 0 ){ parm = parm * -1; } return parm;}

-4arg

References• Returning nonreferences• the return value (object) is copied• e.g., add 1 to absolute value

33

-4arg

parm

int arg = -4;abs(arg)++;cout << arg << endl;

int abs(int& parm){ if( parm < 0 ){ parm = parm * -1; } return parm;}

References• Returning nonreferences• the return value (object) is copied• e.g., add 1 to absolute value

34

-4 4arg

parm

int arg = -4;abs(arg)++;cout << arg << endl;

int abs(int& parm){ if( parm < 0 ){ parm = parm * -1; } return parm;}

References• Returning nonreferences• the return value (object) is copied• e.g., add 1 to absolute value

35

-4 4arg

4tmp

int arg = -4;abs(arg)++;cout << arg << endl;

int abs(int& parm){ if( parm < 0 ){ parm = parm * -1; } return parm;}

References• Returning nonreferences• the return value (object) is copied• e.g., add 1 to absolute value

36

-4 4arg

4 5tmp

int arg = -4;abs(arg)++;cout << arg << endl;

int abs(int& parm){ if( parm < 0 ){ parm = parm * -1; } return parm;}

References• Returning nonreferences• the return value (object) is copied• e.g., add 1 to absolute value

37

4argint arg = -4;abs(arg)++;cout << arg << endl;

int abs(int& parm){ if( parm < 0 ){ parm = parm * -1; } return parm;}

References• Returning a reference• the object itself is returned• returned reference can be assigned new data or updated

38

int arg = -4;abs(arg)++;cout << arg << endl;

int& abs(int& parm){ if( parm < 0 ){ parm = parm * -1; } return parm;}

-4arg

parm

References• Returning a reference• the object itself is returned• returned reference can be assigned new data or updated

39

int arg = -4;abs(arg)++;cout << arg << endl;

int& abs(int& parm){ if( parm < 0 ){ parm = parm * -1; } return parm;}

arg

parm

-4 4

References• Returning a reference• the object itself is returned• returned reference can be assigned new data or updated

40

int arg = -4;abs(arg)++;cout << arg << endl;

int& abs(int& parm){ if( parm < 0 ){ parm = parm * -1; } return parm;}

-4 4arg

tmp

References• Returning a reference• the object itself is returned• returned reference can be assigned new data or updated

41

int arg = -4;abs(arg)++;cout << arg << endl;

int& abs(int& parm){ if( parm < 0 ){ parm = parm * -1; } return parm;}

4 5arg

tmp

References• Returning a reference• the object itself is returned• returned reference can be assigned new data or updated

42

int arg = -4;abs(arg)++;cout << arg << endl;

int& abs(int& parm){ if( parm < 0 ){ parm = parm * -1; } return parm;}

5arg

References• Returning a reference• never return a reference a local object

43

int arg1 = 2;int arg2 = 5;int sum = add(arg1, arg2);

int& add( int& parm1, int& parm2){ int val = parm1 + parm2; return val;}

2arg1

5arg2

References• Returning a reference• never return a reference a local object

44

int arg1 = 2;int arg2 = 5;int sum = add(arg1, arg2);

int& add( int& parm1, int& parm2){ int val = parm1 + parm2; return val;}

2arg1

5arg2

parm2

parm1

References• Returning a reference• never return a reference a local object

45

int arg1 = 2;int arg2 = 5;int sum = add(arg1, arg2);

int& add( int& parm1, int& parm2){ int val = parm1 + parm2; return val;}

2arg1

5arg2

parm2

parm2

7val

References• Returning a reference• never return a reference a local object

46

int arg1 = 2;int arg2 = 5;int sum = add(arg1, arg2);

int& add( int& parm1, int& parm2){ int val = parm1 + parm2; return val;}

2arg1

5arg2

7val

tmp

References• Returning a reference• never return a reference a local object

47

int arg1 = 2;int arg2 = 5;int sum = add(arg1, arg2);

int& add( int& parm1, int& parm2){ int val = parm1 + parm2; return val;}

2arg1

5arg2

7val

sum

Pointers• Pointers are aliases that “point” to other variables• its just another name for an object

• Pointer is a compound type• type *variable;• e.g., int *foo;• should be read from right to left:

“foo is a pointer to an int”

48

Pointers• Alternate (dangerous) way to define pointers• type* variable;• e.g., int* foo;• dangerous: int* pval1, pval2;• pval1 is a pointer to an int• pval2 is an int• properly: int *pval1, *pval2;

49

Pointers• Pointers store the address of the object they alias• this gives us lots of power• more power than references• also more rope

• We need to be able to get the address of objects• use the address-of operator &• e.g., the integer pointer pval is assigned the address of valint val = 7;int *pval = &val;

• can use & on any value that can be on the left-side of an assignment• called lvalues• e.g., variables but not literals 50

Pointers• Valid pointers can have 3 possible values• address of a specific object• one address past the end of a specific object• 0 (or NULL)

• Initializing pointers• pointers do not need to be bound to an object immediately• not valid until initialized to 1 of 3 values above

• Legal assignments to (initialization of) pointers1. constant expression with a value of 02. address of an object with the correct type3. one address past the end of an object4. another valid pointer of the same type 51

Pointers

52

int aval = 21;int *pval1 = &aval;

21aval

pval1

Pointers

53

int aval = 21;int *pval1 = &aval;

21aval

pval1

Pointers

54

int aval = 21;int *pval1 = &aval;

int bval = 5;int *pval2 = &bval;

21aval

pval1

5bval

pval2

Pointers

55

int aval = 21;int *pval1 = &aval;

int bval = 5;int *pval2 = &bval;

pval1 = pval2;

21aval

pval1

5bval

pval2

Pointers• Uninitialized pointers• have some address made up from garbage• whatever was in that memory before• using them is dangerous, may overwrite other objects memory• like a wild card pointer• DO NOT LEAVE POINTERS LAYING AROUND UNINITIALIZED

56

Pointers• Getting access to the object• not automatic like references• need to use the * operator• e.g.,int val = 8;int *pval = &val;cout << *pval << endl;

• Dereferencing a pointer returns the object (an lval)• can assign new data to object• or modify object

57

Pointers

58

int aval = 21;int *pval1 = &aval;

21aval

pval1

Pointers

59

int aval = 21;int *pval1 = &aval;

*pval1 = 5;

21 5aval

pval1

Pointers

60

int aval = 21;int *pval1 = &aval;

*pval1 = 5;

(*pval1)++;

5 6aval

pval1

Pointers• We can also have pointers to pointers• a pointer stores an address of an object• a pointer is an object and also has an address

(different from the one it stores)• just add another * in the initialization to make a pointer to

a pointer• dereferencing a pointer to a pointer, yields the pointer• must dereference twice (**) to get to the object

61

Pointers

62

int aval = 21;int *pval1 = &aval;int **ppval = &pval1;

int bval = 5;int *pval2 = &bval;

21aval

pval1

5bval

pval2

ppval

Pointers

63

int aval = 21;int *pval1 = &aval;int **ppval = &pval1;

int bval = 5;int *pval2 = &bval;

ppval = &pval2;

21aval

pval1

5bval

pval2

ppval

Pointers

64

int aval = 21;int *pval1 = &aval;int **ppval = &pval1;

int bval = 5;int *pval2 = &bval;

ppval = &pval2;**ppval = 8;

21aval

pval1

5 8bval

pval2

ppval

Pointers and Functions

65

int arg1 = 7;int arg2 = 15;swap(&arg1, &arg2);

void swap(int *parm1, int *parm2){ int tmp = *parm1; *parm1 = *parm2; *parm2 = tmp;}

7arg1

15arg2

Pointers and Functions

66

int arg1 = 7;int arg2 = 15;swap(&arg1, &arg2);

void swap(int *parm1, int *parm2){ int tmp = *parm1; *parm1 = *parm2; *parm2 = tmp;}

7arg1

15arg2

parm2

parm1

Pointers and Functions

67

int arg1 = 7;int arg2 = 15;swap(&arg1, &arg2);

void swap(int *parm1, int *parm2){ int tmp = *parm1; *parm1 = *parm2; *parm2 = tmp;}

7 15

15 7

parm1

arg1

arg2

parm2

Pointers and Functions

68

int a = 7;int b = 15int *arg1 = &a;int *arg2 = &b;swap_ptr(arg1, arg2);

void swap_ptr( int *parm1, int *parm2){ int* tmp = parm1; parm1 = parm2; parm2 = tmp;}

7

15

arg1

arg2

Pointers and Functions

69

int a = 7;int b = 15int *arg1 = &a;int *arg2 = &b;swap_ptr(arg1, arg2);

void swap_ptr( int *parm1, int *parm2){ int* tmp = parm1; parm1 = parm2; parm2 = tmp;}

7

15

parm1

arg1

arg2

parm2

Pointers and Functions

70

int a = 7;int b = 15int *arg1 = &a;int *arg2 = &b;swap_ptr(arg1, arg2);

void swap_ptr( int *parm1, int *parm2){ int* tmp = parm1; parm1 = parm2; parm2 = tmp;}

7

15

parm2

arg1

arg2

parm1

Pointers and Functions

71

int a = 7;int b = 15int *arg1 = &a;int *arg2 = &b;swap_ptr(arg1, arg2);

void swap_ptr( int *&parm1, int *&parm2){ int* tmp = parm1; parm1 = parm2; parm2 = tmp;}

7

15

parm2

arg1

arg2

parm1

Pointers and Functions• Never return a pointer to a local object• for the same reasons it is a problem with references

72

Pointers and const• We can have pointers to constant objects• const type *name;• read: name may point to a type that is constant• e.g., const double dbl = 3.7;const double dbl2 = 4.5;const double *pdbl = &dbl;

• it is illegal to try to modify a constant object, even with a pointer• e.g., *pdbl = 2.4; // ERROR

• it is not illegal to assign the pointer to a different object• e.g.,pdbl = &dbl2; 73

Pointers and const• We can have pointers to constant objects• can also point to non-constant objects• e.g., double dbl = 3.7;const double *pdbl = &dbl;

• cannot modify non-constant objects using a pointer to a constant object

• e.g.,*pdbl = 7.1;

• even though the data can be modified by other aliases• e.g.,dbl = 7.1;

74

Pointers and const• We can have also have constant pointers to

non-constant objects• type *const name = …;• means we cannot reassign (rebind) the pointer to another object• must initialize when we create it• e.g.,int val = 7;int val2 = 10;int *const cpval = &val;*cpval = 15; // OKcpval = &val2; // COMPILE ERROR

75

Pointers and const• We can have also have constant pointers to

constant objects• const type *const name = …;• means we cannot reassign (rebind) the pointer to another object• must initialize when we create it• and we cannot modify the object• e.g.,const int val = 7;const int *const cpval = &val;*cpval = 15; // COMPILE ERRORcpval = &val2; // COMPILE ERROR

76

Pointers and Arrays• An array variable is really (sort of) a pointer to the first item in

the array• We can get pointers to elements in the array also• using address-of operator (&)

77

13579

oddsint odds[] = {1,3,5,7,9};int* podds = odds; //OKint* podds = &odds; //ERROR

int* p3rd = &odds[2];

podds

p3rd

Pointers and Arrays• Pointer arithmetic• adding/subtracting an integer to a pointer yields a pointer• use to move around an array• e.g., jump 2 aheadint odds[4] = {1,3,5,7};int* podds = odds;podds = podds + 2; // points to 5

• e.g., pointer to one past the end of the arraypodds = podds + 4;

• Dangerous to dereference pointer one past the end of an array• OK to use to compare to other pointer

• Legal but very dangerous to increment pointer more than 1 past the end (or before the beginning) 78

Pointers and Arrays• Pointer arithmetic• can dereference result of pointer arithmetic• e.g.,int odds[4] = {1,3,5,7};int last_odd = *(odds + 3);

• Parenthesis are crucial here

79

Pointers and Arrays• Subscripts• subscript (e.g., a[4]) is just short hand for: “add 4 to the pointer a

and dereference the result”• can use subscript with any pointer• e.g.,int odds[4] = {1,3,5,7};int* p_end = &odds[4];int last = p_end[-1]; // last item (7)

80

Multidimensional Arrays• An array can store arrays• called a two dimensional array or matrix• first dimension is called row• second dimension is called column

• Initializing• need to provide a length for each dimension• type name[row-dimension][column-dimension]• creates row-dimension arrays each column-dimension long• e.g., int array2d[3][4];

81

Multidimensional Arrays• Initializing• can be statically initialized• e.g., int array2d[3][4] = {

{1, 2, 3, 4}, // row indexed by 0{5, 6, 7, 8}, // row indexed by 1{9, 10, 11, 12} // row indexed by 2

};

82

1

5

9

2

6

10

3

7

11

4

8

12

Multidimensional Arrays• Accessing data• need to use a subscript for each dimension• type name = 2d_array_name[row][column]• e.g., int top_right = array2d[0][3]; // 4

83

1

5

9

2

6

10

3

7

11

4

8

12

0

1

2

30 1 2

rows

columns

Multidimensional Arrays• Accessing data• using only a subscript returns a pointer to the row array• type* pname = 2d_array_name[row]• e.g., int* row1 = array2d[1]; // {5,6,7,8}

84

1

5

9

2

6

10

3

7

11

4

8

12

0

1

2

30 1 2

rows

columns

row1

C-style Strings• String literals (e.g., “foo”) in C++ are stored as const char[]• C-style strings• characters (e.g., ‘f’) are stored in an array of chars• last char is the NULL character ‘\0’ or just plain 0

• A hold over from C• sometimes still used• important to know how they work

85

char ca1[] = {‘C’, ‘+’, ‘+’}; // NOchar ca2[] = {‘C’, ‘+’, ‘+’, ‘\0’}; // YESconst char *cp = “C++”; // compiler adds ‘\0’

C-style Strings• Manipulated using (const) char*

86

bool contains(const char* str, char& letter){ const char* p = str; while( *p != letter && *p != NULL ){ p++; } return( *p == letter );}

cout << contains(“Java”, ‘C’) << endl;

C-style Strings• Standard C library provides functions for C-style strings• int strlen(const char *str)• returns length of str, not including null-terminator

• int strcmp(const char *a, const char* b)• returns 0 if a’s string and b’s string are identical• returns > 0 if a’s string > b’s string• returns < 0 if a’s string < b’s string

87

C-style Strings• Standard C library provides functions for C-style strings• char* strcat(char *destination, char* source)• appends source to destination• puts results into destination• e.g., strcat(“foo”, “bar”) = “foobar”• better have room in destination for

strlen(destination) + strlen(source) + 1 characters• char* strcpy(char* dest, char* source)• copies source into destination• better have room in destination for strlen(source) + 1 characters

88

C-style Strings• Standard C library provides functions for C-style strings• char* strncat(char *destination, char* source, int n)• same as strcat, but only appends n characters• safer version of strcat

• char* strncpy(char* dest, char* source, int n)• same as strcpy, but only copies n characters• safer version of strcpy

89

C-style Strings• Always use these n versions of string copy and concatenate• using strcpy and strcat causes many, many security exploits

• Always remember the null-terminator• strlen won’t work without it• can then cause strncpy & strncat to be wrong

• OR, even better ALWAYS use C++’s string class

90

Questions?

91

Dynamic Allocation• Memory for local objects is automatically created

and reclaimed• memory is created for it at beginning of a function• memory is reclaimed at the end of the function• e.g.,void func(){ int a = 7; if( a == 15 ){ a *= 2; }}

• It would be illegal to try to reference a (use its name) outside of the function func

• What if we want objects that last longer?92

Dynamic Allocation• C++ provides a separate block of memory for this purpose• called the heap or free store • objects allocated (created from) the heap last until they are

deallocated (explicitly returned to the heap)• heap allocated objects do not have names• we access them through pointers

• Allocating this memory is called dynamic allocation• accomplished using the new operator• type *pointer_name = new type;• e.g.,int *pInt = new int;double *pdbl = new double;

93

Dynamic Allocation

94

int aLocal = 21;int *pLocal = &aLocal;

int *pHeap = new int;*pHeap = 34;

21aLocal

pLocal

34pHeap

Dynamic Allocation• Initializing dynamically allocated objects• must use direct-initialization• e.g.,

int *pInt = new int(1024);double* pDbl = new double(3.14);

95

Dynamic Allocation• Deallocating heap objects• when we are done with an object we should return its memory to

the heap• forgetting to deallocate heaps objects is called a memory leak• memory leaks cause programs to grow until they consume all of

the machines memory and crash• delete operator• deallocates heap objects• delete pointer_name;• e.g.,int *pInt = new int(15);... delete pInt; 96

Dynamic Allocation• What happens to pInt after it’s object has be deallocated?• pInt becomes undefined, it is no longer valid• pInt points to memory is no longer owns• called a dangling pointer

• Cleaning up dangling pointers• dangling pointers cause all sorts of programming errors• ALWAYS set a pointer to 0 (or NULL) after deallocating• e.g.,int *pInt = new int(15);...delete pInt;pInt = NULL;

97

Dynamic Allocation• Calling delete on a zero-valued pointer is legal and safe• this is good in case you accidentally delete the same

pointer twice• e.g.,int *pInt = new int(15);...delete pInt;pInt = NULL;...delete pInt;

98

Dynamic Allocation• Dynamic allocation and const• legal to dynamically create constant objects• must be initialized when its created• cannot be changed once initialized• e.g.,const int *pInt = new int(15);

• const heap objects also must be deallocated• e.g.,delete pInt;

99

Dynamic Allocation• Common errors1. Forgetting to delete dynamically allocated memory• causes memory leaks

2. Reading and writing to an object after it has been deleted• overwrites some other object’s memory• avoid by setting pointer to 0 after deleting

3. Deleting the same memory twice• two pointers may point at same heap object• deleting one pointer invalidates the other• calling delete on the other may corrupt the heap• big time bad news

100

Questions?

101

Dynamic Allocation• What if we don’t know how many elements we need in an

array until after we start running?• e.g., make a new C-style string to store the concatenate value of

two other strings• do not know correct size until we call strlen on the other

two strings• e.g., we want to make a variable size tic-tac-toe board• can be 3x3, 4x4, NxN• do not know until user write size on the console

• “Enter Board Size: “

102

Dynamic Allocation• Dynamic allocation of arrays solves this problem• heap can allocate memory at run time based on a variable size• type *array_name = new type[dimension]• returns a pointer to the first element in the array• e.g., int *pIntArray = new int[15];

• Must deallocate later• just like other dynamic allocations• syntax slightly different• delete [] array_name;

103

Dynamic Allocation

104

// ask user for inputcout << "What is the largest prime to find?“;cout << endl;

// get user inputsize_t max_prime;cin >> max_prime;max_prime++;

// i'th entry stores whether number i is a primebool *potential_prime = new bool[max_prime];

//run the sieve …// clean up the memorydelete [] potential_prime;

Questions?

105