Professional Documents
Culture Documents
Fundamental of Programming II
Jimma, Ethiopia.
Objective of the chapter
Explore how to use the new and delete operators to manipulate dynamic
variables.
2
Pointer Data Type and Pointer Variables
An address that is used to name a variable in this way (by giving the
address in memory where the variable starts) is called a pointer because
the address can be thought of as “pointing” to the variable.
4
Declaring Pointer Variables
In C++, you declare a pointer variable by using the asterisk symbol (*) between the data
type and the variable name.
The general syntax to declare a pointer variable is:
dataType *identifier;
Where type is the data type pointed to by the pointer.
As an example, consider the following statements:
int *p;
char *ch;
In these statements, both p and ch are pointer variables of type int and char
respectively.
The content of p points to a memory location of type int,
the content of ch points to a memory location of type char.
Memory addresses, or pointers, allow us to manipulate data much more flexibly;
manipulating the memory addresses of data 5can be more efficient than manipulating the
Cont…
int *p, *q; declares both p and q to be pointer variables of type int.
6
Address of Operator (&)
7
Example
The variable that stores the address of another variable is what in C++ is
called a pointer.
8
Dereferencing Operator (*)
An interesting property of pointers is that they can be used to access the
variable they point to directly.
This is done by preceding the pointer name with the dereference
operator (*). The operator itself can be read as "value pointed to by".
baz = *foo; This could be read as: "baz equal to value pointed to by foo",
10
Cont…
Suppose that the following statements are executed in the order given:
x = 50;
p = &x;
*p = 38;
11
Cont…
After the statement x = 50; executes, the values of &p, p, *p, &x, and x
are as follows:
After the statement p = &x; executes, the values of &p, p, *p, &x, and x
are as follows:
After the statement *p = 38; executes, the values of &p, p, *p, &x, and x
are as follows. (Because *p and x refer to the same memory space, the
value of x is also changed to 38.)
12
Pointer initialization
13
Cont…
14
Example
int x = 5;
int * numPtr=&x;
* numPtr = * numPtr * * numPtr ;
cout << x;
Another example.
int firstvalue, secondvalue;
int * mypointer;
mypointer = &firstvalue;
*mypointer = 10;
mypointer = &secondvalue;
*mypointer = 20;
cout << "firstvalue is " << firstvalue << '\n';
cout << "secondvalue is15" << secondvalue << '\n';
Example
16
Pointers and const
There are two places the const keyword can be placed within a pointer variable
declaration. This is because there are two different variables whose values you
might want to forbid changing: the pointer itself and the value it points to.
const int * ptr ;
declares a changeable pointer to a constant integer. The integer value cannot be
changed through this pointer, but the pointer may be changed to point to a
different constant integer. int x=5; const int* ptr; ptr=&x; but
*ptr=20//impossible.
int * const ptr;
declares a constant pointer to changeable integer data. The integer value can be
changed through this pointer, but the pointer may not be changed to point to a
different constant integer. int x; int *const ptr=&x; *p=90; but
ptr=&val//impossible.
const int * const ptr;
forbids changing either the address ptr contains or the value it points to.
17
Pointers and const
Pointers can be used to access a variable by its address, and this access
may include modifying the value pointed.
But it is also possible to declare pointers that can access the pointed value
to read it, or not to modify it.
int x;
int y = 10;
const int * p = &y;
x = *p; // ok: reading p
*p = x; // error: modifying p, which is const-qualified
18
Operations on Pointer Variables
The operations that are allowed on pointer variables are the assignment
and relational operations and some limited arithmetic operations.
The value of one pointer variable can be assigned to another pointer
variable of the same type.
Two pointer variables of the same type can be compared for equality,
and so on.
int *p, *q;
p = q;
p==q
p != q
To conduct arithmetical operations on pointers is a little different than to
conduct them on regular integer types. To begin with, only addition and
subtraction operations are allowed.
But both addition and subtraction have a slightly different behavior with
pointers, according to the size of the data type to which they19point.
Cont..
20
Cont…
int* p1,*p2;
cout<<p1+p2;//impossible
cout<<p1-p2;//possible
Logical Operations on Pointers
ptr1 > ptr2 is the same as ptr1 - ptr2 > 0,
ptr1 = ptr2 is the same as ptr1 - ptr2 = 0,
ptr1 < ptr2 is the same as ptr1 - ptr2 < 0,
if(p1>p2)//possible: true if memory address of p1 is greater than p2
Suppose now that we define three pointers in this compiler.
char *mychar; short *myshort; long *mylong;
They point to the memory locations 1000, 2000, and 3000, respectively.
++mychar; or mychar = mychar + 1; ++myshort; ++mylong;
21
Cont…
22
Cont…
Regarding the increment (++) and decrement (--) operators, both can be
used as either prefix or suffix of an expression, with a slight difference in
behavior: as a
prefix, the increment happens before the expression is evaluated, and
suffix, the increment happens after the expression is evaluated.
postfix operators, such as increment and decrement, have higher
precedence than prefix operators, such as the dereference operator (*).
23
Cont…
*p++
is equivalent to *(p++). increase the value of p (so it now points to the next
element), but because ++ is used as postfix, the whole expression is evaluated
as the value pointed originally by the pointer (the address it pointed to before
being incremented).
Four possible combinations of the dereference operator with both the prefix and
suffix versions of the increment operator.
*p++ // same as *(p++): increment pointer, and dereference un-incremented
address.
*++p // same as *(++p): increment pointer, and dereference incremented address
++*p // same as ++(*p): dereference pointer, and increment the value it points to
int listofnumber[]={1,5,8,13,15};
int *p;
p= listofnumber;
cout<<"*p++ increment pointer and dereference un-increment value “
<<*p++<<endl;
cout<<"*++p increment pointer, and dereference incremented
address“ <<*++p<<endl;
cout<<"++*p== dereference pointer, and increment the value it points to“
<<++*p<<endl;
cout<<"(*p)++==dereference pointer, and post-increment the value it
points to "<<(*p)++<<endl;
cout<<“After post Increment ”<<*p;
25
Pointers and Arrays
26
Example
int numbers[5];
int * p;
p = numbers; *p = 10;
p++; *p = 20;
p = &numbers[2]; *p = 30;
p = numbers + 3; *p = 40;
p = numbers; *(p+4) = 50;
for (int n=0; n<5; n++)
cout << numbers[n] << ", ";
27
Pointers to pointers
C++ allows the use of pointers that point to pointers, in its turn, point to
data (or even to other pointers).
The syntax simply requires an asterisk (*) for each level of indirection in
the declaration of the pointer:
char a;
char * b;
char ** c;
a = 'z';
b = &a;
c = &b;
assuming the randomly chosen memory locations for each variable
of 7230, 8092, and 10502, could be represented as: variable c, which is a
pointer to a pointer. **c is of type char and a value of 'z‘.
28
Dynamic Variables
Variables that are created during program execution are called dynamic
variables.
With the help of pointers, C++ creates dynamic variables.
C++ provides two operators, new and delete, to create and destroy
dynamic variables, respectively.
When a program requires a new variable, the operator new is used. When
a program no longer needs a dynamic variable, the operator delete is used.
29
Operator new
operator new has two forms: one to allocate a single variable and another
to allocate an array of variables.
new dataType; to allocate a single variable
new dataType[intExp]; to allocate an array of variables
int *p; char *q;
p = new int;
q = new char[16];
The operator new allocates memory (a variable) of the designated type
and returns a pointer to it—that is, the address of this allocated memory.
Moreover, the allocated memory is uninitialized.
Because a dynamic variable is unnamed, it cannot be accessed directly.
It is accessed indirectly by the pointer returned by new.
30
Cont…
The statement:
p = &x;
Stores the address of x in p. However, no new memory is allocated. On
the other hand, consider the following statement:
p = new int;
This statement creates a variable during program execution somewhere
in memory and stores the address of the allocated memory in p. The
allocated memory is accessed via pointer dereferencing—namely, *p.
Similarly, the statement:
q = new char[16];
creates an array of 16 components of type char and stores the base
address of the array in q.
31
Cont..
32
Cont..
Recall that the operator new allocates memory space of a specific type
and returns the address of the allocated memory space.
33
Cont..
34
Cont..
Now the obvious question is what happened to the memory space 1500 that p
was pointing to after execution of the statement in Line 1.
After execution of the statement in Line 3, p points to the new memory space at
location 1800.
The previous memory space at location 1500 is now inaccessible. In addition,
the memory space 1500 remains as marked allocated. In other words, it cannot
be reallocated. This is called memory leak.
That is, there is an unused memory space that cannot be allocated.
What would happen if you executed statements, such as Line 3, a few thousand
or a few million times.
There would be a good amount of memory leak. The program might then run
out of memory spaces for data manipulation and eventually result in an
abnormal termination of the program.
The question at hand is how to avoid memory leak. When a dynamic variable is
no longer needed, it can be destroyed; that
35 is, its memory can be deallocated.
Operator delete
The C++ operator delete is used to destroy dynamic variables. The syntax to
use the operator delete has two forms:
delete pointerVariable; //to deallocate a single dynamic variable
delete [] pointerVariable; //to deallocate a dynamically created array
delete p;
delete [] name;
delete str;
deallocate the memory spaces that the pointers p, name, and str point
to.
Depending on a particular system, after these statements execute, these
pointer variables may still contain the addresses of the deallocated memory
spaces.
In this case, we say that these pointers are dangling to avoid this pitfall is to
set these pointers to NULL after the delete operation.
When a dynamic variable is no longer needed, it can be destroyed; that is, its
memory can be deallocated. 36
Cont…
37
Dynamic array
One of the limitations of a static array is that every time you execute the
program, the size of the array is fixed, so it might not be possible to use the
same array to process different data sets of the same type.
One way to handle this limitation is to declare an array that is large enough
to process a variety of data sets.
However, if the array is very big and the data set is small, such a declaration
would result in memory waste.
On the other hand, it would be helpful if, during program execution, you
could prompt the user to enter the size of the array and then create an array of
the appropriate size.
This approach is especially helpful if you cannot even guess the array size.
38
Cont..
39
Cont...
What is the output of the following code fragment? The code is assumed
to be embedded in a correct and complete program.
int array_size = 10;
int *a;
a = new int[array_size];
int i;
for (i = 0; i < array_size; i++)
*(a + i) = i;
for (i = 0; i < array_size; i++)
cout << a[i] << " ";
cout << endl;
41
What is the output of the following C++ code?
42
What is the output of the following C++ code?
43
What is the output of the following C++ code?