object oriented programming cop3330 /...

31
Object Oriented Programming COP3330 / CGS5409

Upload: others

Post on 04-Jun-2020

14 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

Object Oriented Programming COP3330 / CGS5409

Page 2: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

More pointer review Pass by Address C-style Arrays More DMA

Page 3: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

We've seen that regular function parameters are pass-by-value ◦ A formal parameter of a function is a local variable that will

contain a copy of the argument value passed in ◦ Changes made to the local parameter variable do not affect the

original argument passed in

If a pointer type is used as a function parameter type, then an actual address is being sent into the function instead ◦ In this case, you are not sending the function a data value --

instead, you are telling the function where to find a specific piece of data

◦ Such a parameter would contain a copy of the address sent in by the caller, but not a copy of the target data

◦ When addresses (pointers) are passed into functions, the function could affect actual variables existing in the scope of the caller

Page 4: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

void SquareByAddress(int * ptr) { // modifying the target, *ptr *ptr = (*ptr) * (*ptr); } int main() { int num = 4; cout << "num = " << num << '\n'; // num = 4 SquareByAddress(&num); // address of num passed in cout << "num = " << num << '\n'; // num = 16 }

Page 5: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

With a regular array declaration, you get a pointer for free. The name of the array acts as a pointer to the first element of the array.

int list[10]; // the variable list is a pointer // to the first integer in the array int * p; // p is a pointer. same type as list. p = list; // legal assignment. Both pointers to ints.

In the above code, the address stored in list has been assigned to p.

Now both pointers point to the first element of the array. Now, we could actually use p as the name of the array!

list[3] = 10; p[4] = 5; cout << list[6]; cout << p[6];

Page 6: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

Another useful feature of pointers is pointer arithmetic.

In the previous array example, we referred to an array item with p[6]. We could also say *(p+6).

When you add to a pointer, you do not add the literal number. You add that number of units, where a unit is the type being pointed to.

For instance, p + 6 in the above example means to move the pointer forward 6 integer addresses. Then we can dereference it to get the data *(p + 6).

Page 7: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

What pointer arithmetic operations are allowed? ◦ A pointer can be incremented (++) or decremented

(--) ◦ An integer may be added to a pointer (+ or +=) ◦ An integer may be subtracted from a pointer (- or -

=) ◦ One pointer may be subtracted from another

Page 8: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

The fact that an array's name is a pointer allows easy passing of arrays in and out of functions. When we pass the array in by its name, we are passing the address of the first array element. So, the expected parameter is a pointer.

Example:

// This function receives two integer pointers, // which can be names of integer arrays. int Example1(int * p, int * q);

Page 9: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

The fact that an array's name is a pointer allows easy passing of arrays in and out of functions. When we pass the array in by its name, we are passing the address of the first array element. So, the expected parameter is a pointer.

Example:

// This function receives two integer pointers, // which can be names of integer arrays. int Example1(int * p, int * q);

Page 10: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

When an array is passed into a function (by its name), any changes made to the array elements do affect the original array, since only the array address is copied (not the array elements themselves).

void Swap(int * list, int a, int b) { int temp = list[a]; list[a] = list[b]; list[b] = temp; }

Page 11: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

This Swap function allows an array to be passed in by its name only. The pointer is copied but not the entire array. So, when we swap the array elements, the changes are done on the original array. Here is an example of the call from outside the function:

int numList[5] = {2, 4, 6, 8, 10}; Swap(numList, 1, 4); // swaps items 1 and 4

Note that the Swap function prototype could also be written like

this:

void Swap(int list[], int a, int b);

The array notation in the prototype does not change anything. An array passed into a function is always passed by address, since the array's name IS a variable that stores its address (i.e. a pointer).

Page 12: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

Pass-by-address can be done in returns as well -- we can return the address of an array.

int * ChooseList(int * list1, int * list2) { if (list1[0] < list2[0]) return list1; else return list2; // returns copy of address of array } And an example usage of this function: int numbers[5] = {1,2,3,4,5}; int numList[3] = {3,5,7}; int * p; p = ChooseList(numbers, numList);

Page 13: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

The keyword const can be used on pointer parameters, like we do with references. It is used for a similar situation -- it allows parameter passing without copying anything but an address, but protects against changing the data (for functions that should not change the original)

const typeName * v This establishes v as a pointer to an object that cannot be

changed through the pointer v. Note: This does not make v a constant! The pointer v can be

changed. But, the target of v cannot be changed (through the pointer v).

int Function1(const int * list); // target of list can't be changed in function

Page 14: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

Note: The pointer can be made constant, too. Here are the different combinations:

Non-constant pointer to non-constant data int * ptr;

Non-constant pointer to constant data const int * ptr;

Constant pointer to non-constant data int x = 5; int * const ptr = &x; // must be initialized here

Constant pointer to constant data

int x = 5; const int * const ptr = & x;

Page 15: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

We've seen how to declare a character array and initialize with a string:

char name[20] = "Marvin Dipwart";

Note that this declaration creates an array called name (of size 20), which can be modified. Another way to create a variable name for a string is to use just a pointer:

char* greeting = "Hello";

However, this does NOT create an array in memory that can be modified. Instead, this attaches a pointer to a fixed string, which is typically stored in a "read only" segment of memory (cannot be changed

Page 16: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

So it's best to use const on this form of declaration:

const char* greeting = "Hello"; // better

Note: It would be legal to modify the contents of name above, but it would NOT be legal to modify the contents of greeting:

name[1] = 'e'; // name now "Mervin Dipwart" greeting[1] = 'u'; // ILLEGAL!

Page 17: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

These two examples illustrate the above declarations (name and greeting). Note that in both of them, output of the string is done the same way, regardless of the type of declaration. But they differ in the attempts to change the string contents:

str1.cpp -- This one uses the first declaration of greeting (non-const pointer). Note that the attempt to change the contents will compile, but execution results in a run-time error

str2.cpp -- This one uses the second declaration of greeting (const used with the pointer). The attempt to change the target, therefore, will not compile.

Page 18: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

There are two ways that memory gets allocated for data storage:

Compile Time (or static) Allocation ◦ Memory for named variables is allocated by the compiler ◦ Exact size and type of storage must be known at compile time ◦ For standard array declarations, this is why the size has to be

constant Dynamic Memory Allocation ◦ Memory allocated "on the fly" during run time ◦ dynamically allocated space usually placed in a program

segment known as the heap or the free store ◦ Exact amount of space or number of items does not have to be

known by the compiler in advance. ◦ For dynamic memory allocation, pointers are crucial

Page 19: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

We can dynamically allocate storage space while the program is running, but we cannot create new variable names "on the fly"

For this reason, dynamic allocation requires two steps: ◦ Creating the dynamic space. ◦ Storing its address in a pointer (so that the space

can be accessed) To dynamically allocate memory in C++, we

use the new operator.

Page 20: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

• De-allocation is the "clean-up" of space being used for variables or other data storage

• Compile time variables are automatically de-allocated based on their known extent (this is the same as scope for "automatic" variables)

• It is the programmer's job to de-allocate dynamically created space

• To de-allocate dynamic memory, we use the delete operator

Page 21: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

To allocate space dynamically, use the unary operator new, followed by the type being allocated. new int; // dynamically allocates an int new double; // dynamically allocates a double

If creating an array dynamically, use the same form, but put brackets with a size after the type:

new int[40]; // dynamically allocates an array of 40 ints new double[size]; // dynamically allocates array of size doubles

Note that the size can be a variable!

Page 22: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

These statements above are not very useful by themselves, because the allocated spaces have no names! BUT, the new operator returns the starting address of the allocated space, and this address can be stored in a pointer:

int * p; // declare a pointer p p = new int; // dynamically allocate an int and load address into p

double * d; // declare a pointer d d = new double; // dynamically allocate a double and load address into d

// we can also do these in single line statements int x = 40; int * list = new int[x]; float * numbers = new float[x+10];

Notice that this is one more way of initializing a pointer to a valid

target (and the most important one).

Page 23: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

So once the space has been dynamically allocated, how do we use it?

For single items, we go through the pointer. Dereference the pointer to reach the dynamically created target:

int * p = new int; // dynamic integer, pointed // to by p

*p = 10; // assigns 10 to the // dynamic integer cout << *p; // prints 10

Page 24: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

For dynamically created arrays, you can use either pointer-offset notation, or treat the pointer as the array name and use the standard bracket notation:

double * numList = new double[size];// dynamic array

for (int i = 0; i < size; i++) numList[i] = 0; // initialize array vars to 0

numList[5] = 20; // bracket notation *(numList + 7) = 15; // pointer-offset notation // means same as numList[7]

Page 25: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

To deallocate memory that was created with new, we use the unary operator delete. The one operand should be a pointer that stores the address of the space to be deallocated:

int * ptr = new int; // dynamically created int // ... delete ptr; // deletes space that ptr points to

Note that the pointer ptr still exists in this example. That's a named

variable subject to scope and extent determined at compile time. It can be reused:

ptr = new int[10]; // point p to a brand new array

To de-allocate a dynamic array, use this form:

delete [] name_of_pointer;

Page 26: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

Example:

int * list = new int[40]; // dynamic array

delete [] list; // de-allocates the array list = 0; // reset list to null pointer

After de-allocating space, it's always a good idea to

reset the pointer to null unless you are pointing it at another valid target right away.

To consider: So what happens if you fail to de-

allocate dynamic memory when you are finished with it? (i.e. why is de-allocation important?)

Page 27: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

If you have an existing array, and you want to make it bigger (add array cells to it), you cannot simply append new cells to the old ones.

Arrays are stored in consecutive memory, and you never know whether or not the memory immediately after the array is already allocated for something else. For that reason, the process takes a few more steps. Here is an example using an integer array. Let's say this is the original array:

int * list = new int[size];

Page 28: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

Suppose I want to resize this so that the array called list has space for 5 more numbers (presumably because the old one is full).

There are four main steps. ◦ 1. Create an entirely new array of the appropriate type and of

the new size. (You'll need another pointer for this).

int * temp = new int[size + 5]; ◦ 2. Copy the data from the old array into the new array (keeping

them in the same positions). This is easy with a for-loop.

for (int i = 0; i < size; i++) temp[i] = list[i];

Page 29: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

◦ 3. Delete the old array -- you don't need it anymore!

delete [] list; // deletes array pointed to by "list" ◦ 4. Change the pointer. You still want the array to be called "list"

(its original name), so change the list pointer to the new address.

list = temp;

That's it! The list array is now 5 larger than the previous one, and it has the same data in it that the original one had. But, now it has room for 5 more items.

Page 30: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the

More complex example, involving arrays of objects and lots of composition of objects:

Blackjack Example

basic structure ◦ has-a relationships ◦ array use ◦ tracking variables used with the arrays

Page 31: Object Oriented Programming COP3330 / CGS5409ww2.cs.fsu.edu/~mitchell/cop3330-fa2010/slides/rec7.pdf · With a regular array declaration, you get a pointer for free. The name of the