arrays and pointers joe meehean. arrays what if we want to store multiple items? e.g., points scored...
TRANSCRIPT
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 = 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
• 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
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• 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
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
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;