What We Will Cover
Continuations
^ top
12.1: Pointers
Objectives
At the end of the lesson the student will be able to:
- Declare pointers and initialize pointer variables
- Code basic pointer operations
- Describe dynamic memory management
|
^ top
12.1.1: Pointer Variables
- Pointer variables (pointers) store memory addresses rather than actual values
- Pointers "point" to a variable by telling where the variable is located
- Recall that memory addresses are numbered locations
- Pointer variables store the value of a memory location
- You have used pointers already!
- Call-by-reference parameters
- Address of actual argument was passed
- Using pointers, you can control low-level memory operations of a computer
- This control can increase the capabilities of the C++ programs you write
- However, this low level control has a price as well
- It is possible to create errors that can crash a program or even freeze a computer
Declaring Pointers
- Pointer variables must be declared to have a pointer type
- For example, to declare a pointer variable named
ptr:
double *ptr;
The asterisk identifies the variable ptr as a pointer
You can declare multiple pointers in a statement:
int *p1, *p2, v1, v2;
p1 and p2 point to variables of type int
v1 and v2 are variables of type int
^ top
12.1.2: Assigning Values to Pointers
- You can use the "address of" operator (
&) to assign addresses to pointers
- For example:
p1 = &v1;
p1 is now a pointer to v1
v1 can be called v1 or "the variable pointed to by p1"
Addresses and Numbers
- A pointer is a memory address and you can display an address using
cout
cout << p1 << endl;
Memory addresses are shown in a heaxadecimal format
Example Assigning Values to Pointers
1
2
3
4
5
6
7
8
9
10
11
12
|
#include <iostream>
using namespace std;
int main() {
int *p1, *p2, v1, v2;
p1 = &v1;
p2 = &v2;
cout << p1 << endl;
cout << p2 << endl;
return 0;
}
|
^ top
12.1.3: The Dereferencing Operator
- C++ uses the
* operator in yet another way with pointers
- The phrase "The variable pointed to by
p" is translated into C++ as "*p"
- Here the
* is known as the dereferencing operator
p is said to be dereferenced
- When you dereference a pointer, you can use it like an actual variable
- For example, you can assign a value to a dereferenced variable like in the following example
Example Using Pointer Dereferencing
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#include <iostream>
using namespace std;
int main() {
int *p1, *p2, v1, v2;
v1 = 1234;
v2 = 0;
p1 = &v1; // v1 and *p1 now refer to the same variable
p2 = &v2;
*p2 = 42; // dereferenced pointer assigned a value
cout << "v1=" << v1 << endl;
cout << "*p1=" << *p1 << endl;
cout << "v2=" << v2 << endl;
cout << "*p2=" << *p2 << endl;
return 0;
}
|
^ top
12.1.4: Using the Assignment Operator
- You can use the assignment operator (
=) to assign the value of one pointer to another
- For example, if
p1 still points to v1:
p2 = p1;
Now *p2, *p1, and v1 all refer to the same variable
Be careful when making assignments to pointer variables:
p1= p2; // changes the location to which p1 "points"
*p1 = *p2; // changes the value at the location to which
// p1 "points"
Pointer Assignment: from the textbook p. 620
Example: Pointer Assignment vs. Dereferenced-Pointer Assignment
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
#include <iostream>
using namespace std;
int main() {
int *p1, *p2, v1, v2;
cout << "First example:" << endl;
p1 = &v1;
p2 = &v2;
*p1 = 84;
*p2 = 99;
p1 = p2;
cout << p1 << "=" << *p1 << endl;
cout << p2 << "=" << *p2 << endl;
cout << "\nSecond example:" << endl;
p1 = &v1;
p2 = &v2;
*p1 = 84;
*p2 = 99;
*p1 = *p2;
cout << p1 << "=" << *p1 << endl;
cout << p2 << "=" << *p2 << endl;
return 0;
}
|
^ top
12.1.5: Dynamic Variables
- Using pointers, variables can be manipulated even without an identifier for them
- For example, to create a pointer to a new "nameless" variable of type
int:
p1 = new int;
The new variable is referred to as *p1
You can use *p1 anyplace you can use an integer variable
cin >> *p1;
*p1 = *p1 + 7;
Variables created using the new operator are called dynamic variables
Dynamic variables are created and destroyed while the program is running
Dynamically creating and destroying variables is called dynamic memory management
Example Demonstrating Pointers and Dynamic Variables
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
//Program to demonstrate pointers and dynamic variables
#include <iostream>
using namespace std;
int main(void) {
int *p1, *p2;
p1 = new int;
*p1 = 42;
p2 = p1;
cout << "*p1 == " << *p1 << endl;
cout << "*p2 == " << *p2 << endl;
*p2 = 53;
cout << "*p1 == " << *p1 << endl;
cout << "*p2 == " << *p2 << endl;
p1 = new int;
*p1 = 88;
cout << "*p1 == " << *p1 << endl;
cout << "*p2 == " << *p2 << endl;
cout << "Hope you got the point of this example!\n";
return 0;
}
|
^ top
12.1.6: Dynamic Class Variables
- Using operator
new with class types calls a constructor as well as allocating memory
- If
Product is a class type, then:
// Creates a pointer to a variable of type Product
Product *prodPtr, *milkPtr;
// Calls the default constructor
prodPtr = new Product;
// Calls Product(string, double);
milkPtr = new Product("Milk", 2.99);
Calling Functions
- To call a function of an object pointed to by a pointer, you must first dereference the pointer
// Dereferencing object variables
(*prod).show();
(*milk).show();
Note that a dereference operator has a lower precedence than a dot (.) operator
Thus you need to enclose the dereference operation in parenthesis
Since using parenthesis requires extra typing, C++ has a special pointer operator: ->
Using "pointer notation" for the above:
// Using "pointer" notation
prod->show();
milk->show();
Dynamic Memory Management
- C++ programs reserve an area of memory called the freestore or heap
- New dynamic variables use memory in the freestore
- If all of the freestore is used, calls to
new will fail
- You can delete and recycle memory that is no longer needed
- Use the
delete operator to return memory to the freestore
- For example:
// Free up memory
delete prod;
delete milk;
Memory used by the variable that ptr pointed to is released to the freestore
The value of ptr is now undefined
Using delete on a pointer variable destroys the dynamic variable pointed to
If another pointer variable was pointing to the dynamic variable, that variable is also undefined
Undefined pointer variables are called dangling pointers
Dereferencing a dangling pointer (*milk) is usually disastrous
To prevent this, you should set the pointer variables to NULL after you delete them
// Make sure we cannot use again
prod = NULL;
milk = NULL;
Now trying to use the pointer variables will cause an exception like:
3 [main] ptrclass 2316 handle_exceptions:
Exception: STATUS_ACCESS_VIOLATION
2095 [main] ptrclass 2316 open_stackdumpfile:
Dumping stack trace to ptrclass.exe.stackdump
Then you will know you have made an error
Rather than the program working part of the time
Example Creating Dynamic Objects
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
#include <iostream>
#include "Product.cpp"
using namespace std;
int main() {
Product *prod, *milk;
// Create two Product objects using pointers
prod = new Product;
milk = new Product("Milk", 2.99);
// Dereferencing object variables
(*prod).show();
(*milk).show();
// Using "pointer" notation
prod->show();
milk->show();
// Free up memory
delete prod;
delete milk;
// Make sure we cannot use again
prod = NULL;
milk = NULL;
milk->show();
return 0;
}
|
Product Class File
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
#include <iostream>
using namespace std;
class Product {
public:
// Constructors
Product();
Product(string newName, double newPrice);
// Instance functions
string getName() { return name; }
double getPrice() { return price; }
void setName(string newName);
void setPrice(double newPrice);
void show();
private:
// Instance variables
string name;
double price;
};
// no-arg constructor
Product::Product() {
name = "Unknown";
price = 0.0;
}
Product::Product(string newName, double newPrice) {
setName(newName);
setPrice(newPrice);
}
void Product::setName(string newName) {
if (newName.length() == 0) {
name = "Unknown";
} else {
name = newName;
}
}
void Product::setPrice(double newPrice) {
if (newPrice > 0.0) {
price = newPrice;
} else {
price = 0.0;
}
}
void Product::show() {
cout << name << " has a price of $"
<< price << endl;
}
|
^ top
12.1.7: Summary
- Pointer variables (pointers) store memory addresses rather than actual values
- A memory address tells where a variable is stored
- Pointers "point" to a variable by telling where the variable is located
- Using pointers, you can control low-level memory operations of a computer
- To declare a pointer, use an asterisk operator
double *ptr;
You can use the "address of" operator (&) to assign addresses to pointers
p1 = &v1;
You can also use the asterisk operator to dereference pointers
*p1 = 42;
You can use the assignment operator = to assign the value of one pointer to another
p2 = p1;
Which should not be confused with:
*p1 = *p3;
You can create dynamic variables using the new operator
p1 = new int;
To destroy dynamic variables, use the delete operator
delete p1;
Also, you can create dynamic object variables
^ top
Exercise 12.1
In this exercise we explore declaring dynamic variables.
Specifications
- Save the following code file as
mypointers.cpp.
- Write a declaration for a variable called
numberPtr that points to integer values.
- Assign the value
54 to the numberPtr variable.
- Write a declaration for a variable called
charPtr that will point to character values.
- Assign the value
'a' to the charPtr variable.
- Write code to display on the screen both dynamic variables.
1
2
3
4
5
6
7
8
9
10
|
#include <iostream>
using namespace std;
int main() {
// Declaration for a variable called numberPt
// Declaration for a variable called charPtr
return 0;
}
|
^ top
12.2: Dynamic Arrays
Objectives
At the end of the lesson the student will be able to:
- Describe the similarities between array variables and pointers
- Use dynamic arrays in programs
|
^ top
12.2.1: Arrays and Pointers
- Array variables are really pointer variables
- Recall that array elements are stored sequentially in memory addresses
- An array variable 'points to' the first indexed variable
- Thus an array variable is a kind of pointer variable
- For example:
int a[] = { 1, 2, 3, 4, 5 };
int *p;
Both a and p are pointer variables
You can assign a to p
p = a;
Variable p now points where a points
Now you can use array brackets with pointer variable p
p[0] = 10;
Note that variable a cannot be changed because it is a constant variable
a = p; // ILLEGAL!
Example Assigning an Array to a Pointer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#include <iostream>
using namespace std;
int main() {
int a[] = { 1, 2, 3, 4, 5 };
int *p;
p = a;
p[0] = 99;
for (int i = 0; i < SIZE; i++) {
cout << p[i] << endl;
}
return 0;
}
|
^ top
12.2.2: Creating and Deleting Dynamic Arrays
- Arrays are limited because you must set the size before you run your program
- You do not always know the size your program will need
- The best you can do is estimate the maximum size
- You can use dynamic arrays to get around this limitation
Creating Dynamic Arrays
- To create a dynamic array, you use the
new operator
const int SIZE = 5;
int *p = new int[SIZE];
Creates a dynamically allocated array of 5 elements with a base type of int
Accessing Array Elements
- Once a dynamic array is declared, you use it like a non-dynamic array
for (int i = 0; i < SIZE; i++) {
p[i] = i * 2 + 1;
cout << p[i] << endl;
}
Deleting Dynamic Arrays
- Since a dynamic array is allocated dynamically at run-time, you need to delete it when finished
- This de-allocates all memory for the dynamic array
delete [] p;
Use brackets to Brackets indicate you are deallocating an array type
Since p still points to the location in memory, you should set p = NULL
p = NULL;
Example of a Dynamic Array
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#include <iostream>
using namespace std;
const int SIZE = 5;
int main() {
// Declaring a dynamic array
int *p = new int[SIZE];
// Accessing a dynamic array
for (int i = 0; i < SIZE; i++) {
p[i] = i * 2 + 1;
cout << p[i] << endl;
}
// Deleting a dynamic array
delete [] p;
p = NULL;
return 0;
}
|
^ top
12.2.3: Using Dynamic Arrays with Functions
- Recall that array types are NOT allowed as the return-type of function
int [] someFunction(); // ILLEGAL!
However, you can return a pointer from a function
Thus, you can return a pointer to an array base type
int* someFunction(); // LEGAL!
For Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
#include <iostream>
using namespace std;
int* makeArray(int length, int value);
void showArray(int values[], int length);
int main(void) {
int arraySize, arrayValue;
cout << "How large of an array do you want? ";
cin >> arraySize;
cout << "What value for each element? ";
cin >> arrayValue;
int* p = makeArray(arraySize, arrayValue);
showArray(p, arraySize);
delete [] p;
p = NULL;
return 0;
}
int* makeArray(int length, int value) {
int* array = new int[length];
for (int i = 0; i < length; i++) {
array[i] = value;
}
return array;
}
void showArray(int values[], int length) {
for (int i = 0; i < length; i++) {
cout << values[i] << " ";
}
cout << endl;
}
|
^ top
12.2.4: Summary
- A dynamically allocated array has its size determined when the program is running
- Dynamic arrays are implemented as a dynamic variable of an array type
int *p = new int[10];
Since a dynamic array is allocated dynamically at run-time, you should destroy it at run time as well
delete [] p;
You can return a pointer to an array base type from a function
int* someFunction();
^ top
Exercise 12.2
In this exercise we explore declaring, allocating and assigning values to dynamic arrays.
Specifications
- Save the following code file as
mydynarray.cpp.
- Compile and run the code to observe how it runs.
- Declare a pointer to a dynamic array.
- Create a dynamic array using the size entered by the user.
- Code a call to the
fillup() function with the dynamic array you created.
- Code a call to the
showArray() function with the dynamic array after the fillup() function.
- Delete the dynamic array when done using it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
#include <iostream>
using namespace std;
void fillUp(int data[], int size);
void showArray(int values[], int size);
int main() {
int size = 0;
// Declare a pointer to a dynamic array
cout << "How many values: ";
cin >> size;
// Create the dynamic array
// Call fillup() function with the dynamic array
cout << "You entered " << size << " numbers:\n";
// Call showArray() function with the dynamic array
// Delete the dynamic array
return 0;
}
void fillUp(int data[], int length) {
cout << "Enter " << length << " numbers:\n";
for (int i = 0; i < length; i++) {
cin >> data[i];
}
}
void showArray(int values[], int size) {
for (int i = 0; i < size; i++) {
cout << values[i] << endl;
}
}
|
^ top
Wrap Up
^ top
Home
| WebCT
| Announcements
| Day Schedule
| Eve Schedule
Course info
| Help
| FAQ's
| HowTo's
| Links
Last Updated: December 01 2005 @17:18:27
|