Lecture 1
-
Upload
williamsock -
Category
Documents
-
view
212 -
download
0
description
Transcript of Lecture 1
Pointers Pointers Function TemplatesFunction TemplatesClass TemplatesClass Templates
Lecture#2Lecture#2
POINTER OVERVIEWPOINTER OVERVIEW
A pointer provides a way of accessing a A pointer provides a way of accessing a variable (or a more complex kind of data, variable (or a more complex kind of data, such as an array) without referring to the such as an array) without referring to the variable directly.variable directly.
The mechanism used for this is the The mechanism used for this is the address of the variableaddress of the variable. In effect, the . In effect, the address acts as an intermediary between address acts as an intermediary between the variable and the program accessing the variable and the program accessing it.it.
POINTER OVERVIEWPOINTER OVERVIEW
In a similar way, a program statement can In a similar way, a program statement can refer to a variable indirectly, using the refer to a variable indirectly, using the address of the variable as a sort of post address of the variable as a sort of post office box or hollow tree for the passing of office box or hollow tree for the passing of information.information.
Why are pointers used?Why are pointers used? Pointers are used in situations when Pointers are used in situations when
passing actual values is difficult or passing actual values is difficult or undesirable.undesirable.
POINTER OVERVIEWPOINTER OVERVIEW Some reasons to use pointers are:Some reasons to use pointers are:
To return more than one value from a function.To return more than one value from a function. To pass arrays and strings more conveniently from To pass arrays and strings more conveniently from
one function to another.one function to another. To manipulate arrays more easily by moving pointers To manipulate arrays more easily by moving pointers
to them (or to parts of them), instead of moving the to them (or to parts of them), instead of moving the arrays themselves. arrays themselves.
To create complex data structures, such as linked lists To create complex data structures, such as linked lists and binary trees, where one data structure must and binary trees, where one data structure must contain references to other data structure.contain references to other data structure.
To communicate information about memory, as in the To communicate information about memory, as in the function malloc( )/new, which returns the location of function malloc( )/new, which returns the location of the free memory by using a pointer. the free memory by using a pointer.
Pointer VariablesPointer Variables
int* ptr;int* ptr; Asterisk means pointer toAsterisk means pointer to Statement defines Statement defines ptrptr as a pointer to as a pointer to intint This variable can hold the This variable can hold the address ofaddress of integer integer
variablesvariables
char* cptr;//pointer to charchar* cptr;//pointer to char
int* iptr;//pointer to intint* iptr;//pointer to int
float* fptr;//pointer to floatfloat* fptr;//pointer to float
Distance* distptr; //pointer to user-defined Distance Distance* distptr; //pointer to user-defined Distance classclass
Accessing the ContentsAccessing the Contents
If we know the address of a variable If we know the address of a variable and don’t know its name. Can we and don’t know its name. Can we access the contents of this variable?access the contents of this variable?
There is a special syntax to access There is a special syntax to access the value/contents of a variable the value/contents of a variable using its address.using its address.
Accessing the ContentsAccessing the Contents
int main()int main()
{{
int var1=11;int var1=11;
int* ptr;int* ptr;
ptr=&var1;ptr=&var1;
cout << *ptr << endlcout << *ptr << endl;//prints contents of pointer(11);//prints contents of pointer(11)
//* acts as indirection operator//* acts as indirection operator
}}
Declaration Vs IndirectionDeclaration Vs Indirection
Asterisk used as the indirection operator has Asterisk used as the indirection operator has a different meaning then the asterisk used to a different meaning then the asterisk used to declare pointer variables.declare pointer variables.
Indirection operator precedes the variable and Indirection operator precedes the variable and means means value of the variable pointed to byvalue of the variable pointed to by..
The asterisk used in the declaration means The asterisk used in the declaration means pointer topointer toint* ptr;//declaration: pointer to intint* ptr;//declaration: pointer to int*ptr = 37;//indirection: value of variable pointed to *ptr = 37;//indirection: value of variable pointed to
by ptrby ptr
Pointers and ArraysPointers and Arrays
There is a close association between There is a close association between pointers and arrayspointers and arrays
These two expressions have exactly These two expressions have exactly the same effect:the same effect:intarray[j]intarray[j]
*(intarray+j)//using indirection operator*(intarray+j)//using indirection operator
Pointers and FunctionsPointers and Functions
Passing arguments by pointerPassing arguments by pointer#include <iostream.h>#include <iostream.h>void increment(int void increment(int **); ); void main(void)void main(void){{int tvar = 10;int tvar = 10;increment(increment(&&tvar);tvar);cout << tvar;cout << tvar;}}void increment(int void increment(int **counter)counter){{**counter = 11;counter = 11;//acts as tvar = 11//acts as tvar = 11}}
Passing ArraysPassing Arrays
const int MAX=5;const int MAX=5;void main()void main(){{void centimize(double*);//prototypevoid centimize(double*);//prototypedouble varray[MAX]={10.0,43.1,95.9,59.7,87.3};double varray[MAX]={10.0,43.1,95.9,59.7,87.3};centimize(varray);centimize(varray);//since the name of an array is array’s address, there is no need for &//since the name of an array is array’s address, there is no need for &……}}Void centimize(double* ptrd)Void centimize(double* ptrd){{for(int j=0; j<MAX;j++)for(int j=0; j<MAX;j++)
*ptrd++ *= 2.54;//ptrd points to element of array *ptrd++ *= 2.54;//ptrd points to element of array }}
const Modifier and Pointersconst Modifier and Pointers
There are two possibilitiesThere are two possibilitiesconst int* ptrcint; // ptrcint is a pointer to constant intconst int* ptrcint; // ptrcint is a pointer to constant int
int* const cptrint; // cptrint is a constant pointer to intint* const cptrint; // cptrint is a constant pointer to int In first declaration, you can’t change the value of In first declaration, you can’t change the value of
whatever cptrint points to, although you can whatever cptrint points to, although you can change cptrint itself.change cptrint itself.
In second declaration, you can change what In second declaration, you can change what ptrcint points to, but you can’t change the value ptrcint points to, but you can’t change the value of ptrcint itself.of ptrcint itself.
Memory ManagementMemory Management
If we use arrays for data storage, we must know If we use arrays for data storage, we must know at the time we write the program at the time we write the program how big the how big the array will be.array will be.Cin<<size;//get size from userCin<<size;//get size from user
Int arr[size];//error: array size must be a constantInt arr[size];//error: array size must be a constant C++ provides a new approach to obtaining blocks C++ provides a new approach to obtaining blocks
of memory: the new operator.of memory: the new operator. This versatile operator obtains memory from the This versatile operator obtains memory from the
operating system and returns a pointer to its operating system and returns a pointer to its starting point.starting point.
The new OperatorThe new Operator#include<iostream.h>#include<iostream.h>
#include<cstring>#include<cstring>
int main()int main()
{{
char* str="self conquest is the greatest victory";char* str="self conquest is the greatest victory";
int len = strlen(str);int len = strlen(str);
char* ptr;char* ptr;
ptr = new char[len+1];//set aside memory: string + ‘\0’ptr = new char[len+1];//set aside memory: string + ‘\0’
strcpy(ptr, str);strcpy(ptr, str);
cout << ptr << endl;cout << ptr << endl;
delete[] ptr;//release ptr’s memory delete[] ptr;//release ptr’s memory
return 0;return 0;
}}
TemplatesTemplates
C++ supports code reuse in different C++ supports code reuse in different ways. ways.
The template feature in C++ The template feature in C++ provides way to reuse source code.provides way to reuse source code.
Function TemplatesFunction Templates
Suppose you want to write a function that Suppose you want to write a function that returns the absolute value of a number. returns the absolute value of a number.
Ordinarily, this function would be written for a Ordinarily, this function would be written for a particular data type:particular data type:int abs(int n) // absolute value of intsint abs(int n) // absolute value of ints{{return (n<0) ? -n : n; // if n is negative, return –n return (n<0) ? -n : n; // if n is negative, return –n }}
Here the function is defined to take an Here the function is defined to take an argument of type argument of type intint and to return a value of and to return a value of this same type.this same type.
Function TemplatesFunction Templates
But now suppose you want to find the absolute value of But now suppose you want to find the absolute value of a type a type longlong. You need to write a completely new . You need to write a completely new function:function:long abs(long n) // absolute value of longslong abs(long n) // absolute value of longs{ { return (n<0) ? -n : n; return (n<0) ? -n : n; }}
And again, for type And again, for type floatfloat::float abs(float n) // absolute value of floatsfloat abs(float n) // absolute value of floats{{return (n<0) ? -n : n;return (n<0) ? -n : n;}}
Function TemplatesFunction Templates
The body of the function is the same in each The body of the function is the same in each case, but they must be case, but they must be separate functionsseparate functions because they handle variables of different types.because they handle variables of different types.
It’s true that in C++ these functions can all be It’s true that in C++ these functions can all be overloadedoverloaded to have the same name, but you must to have the same name, but you must nevertheless write a separate definition for each nevertheless write a separate definition for each one.one.
Rewriting the same function bodyRewriting the same function body over and over over and over for different types Wastes time as well as space for different types Wastes time as well as space in the listing.in the listing.
Function TemplatesFunction Templates
Also, if you find you’ve made an Also, if you find you’ve made an errorerror in one such in one such function, you’ll need to remember to correct it in function, you’ll need to remember to correct it in each function body. Failing to do this correctly is each function body. Failing to do this correctly is a good way to introduce inconsistencies into your a good way to introduce inconsistencies into your program.program.
It would be nice if there were a way to It would be nice if there were a way to write such write such aa function just oncefunction just once and have it work for many and have it work for many different data types. This is exactly what Function different data types. This is exactly what Function templates do for you.templates do for you.
Function TemplatesFunction Templates// template used for absolute value function// template used for absolute value function#include <iostream.h>#include <iostream.h>template <class T> template <class T> // function template// function templateT T abs(abs(TT n)n){ return (n < 0) ? -n : n; }{ return (n < 0) ? -n : n; }void main()void main(){{ int int1 = 5;int int1 = 5;
int int2 = -6;int int2 = -6;long lon1 = 70000;long lon1 = 70000;long lon2 = -80000;long lon2 = -80000;double dub1 = 9.95;double dub1 = 9.95;double dub2 = -10.15; // calls instantiate functionsdouble dub2 = -10.15; // calls instantiate functionscout << "abs(" << int1 << ")=" << cout << "abs(" << int1 << ")=" << abs(int1) abs(int1) << endl; // abs(int)<< endl; // abs(int)cout << "abs(" << int2 << ")=" << cout << "abs(" << int2 << ")=" << abs(int2) abs(int2) << endl; // abs(int)<< endl; // abs(int)cout << "abs(" << lon1 << ")=" << cout << "abs(" << lon1 << ")=" << abs(lon1) abs(lon1) << endl; // abs(long)<< endl; // abs(long)cout << "abs(" << lon2 << ")=" << cout << "abs(" << lon2 << ")=" << abs(lon2) abs(lon2) << endl; // abs(long)<< endl; // abs(long)cout << "abs(" << dub1 << ")=" << cout << "abs(" << dub1 << ")=" << abs(dub1) abs(dub1) << endl; // abs(double)<< endl; // abs(double)cout << "abs(" << dub2 << ")=" << cout << "abs(" << dub2 << ")=" << abs(dub2) abs(dub2) << endl; // abs(double)<< endl; // abs(double)
}}
OUTPUT:
abs(5)=5
abs(-6)=6
abs(70000)=70000
abs(-80000)=80000
abs(9.95)=9.95
abs(-10.15)=10.15
Function TemplatesFunction Templates
The key The key innovationinnovation in function templates is to in function templates is to represent the data type used by the function not as a represent the data type used by the function not as a specific typespecific type such as such as intint, but by a name that can stand , but by a name that can stand for any type. for any type.
In the function template above, this name is In the function template above, this name is TT.. The The templatetemplate keyword signals the compiler that I’m keyword signals the compiler that I’m
about to define a Function template. about to define a Function template. The keyword The keyword classclass, within the angle brackets, might , within the angle brackets, might
just as well be called type. As you’ve seen, you can just as well be called type. As you’ve seen, you can define your own data types using classes, so there’s define your own data types using classes, so there’s really no distinction between types and classes. really no distinction between types and classes.
The variable following the keyword class (The variable following the keyword class (TT in this in this example) is called the example) is called the template argumenttemplate argument..
Function TemplatesFunction Templates
What does the What does the compilercompiler do when it sees the do when it sees the templatetemplate keyword and the Function definition that follows it?keyword and the Function definition that follows it?
The function template itself doesn’t cause the compiler The function template itself doesn’t cause the compiler to generate any code. to generate any code.
It can’t generate code because it doesn’t know yet what It can’t generate code because it doesn’t know yet what data type the function will be working with. data type the function will be working with.
It simply remembers the template for possible future use. It simply remembers the template for possible future use. Code generation doesn’t take place Code generation doesn’t take place until the function is until the function is
actually called (invoked)actually called (invoked) by a statement within the by a statement within the program. This happens in expressions such as abs(int1) program. This happens in expressions such as abs(int1) in the Statementin the Statementcout << "abs(" << int << ")=" << abs(int1);cout << "abs(" << int << ")=" << abs(int1);
Function TemplatesFunction Templates
When the compiler sees a function call, it When the compiler sees a function call, it knows that the type to use is int, because knows that the type to use is int, because that’s the type of the argument that’s the type of the argument int1int1..
So it generates a specific version of the So it generates a specific version of the abs()abs() function for type function for type intint, substituting , substituting intint wherever wherever it sees the name it sees the name TT in the function template. in the function template.
This is called This is called instantiating the function instantiating the function templatetemplate, and each instantiated version of , and each instantiated version of the function is called a the function is called a template functiontemplate function..
Function TemplatesFunction Templates
Notice that the amount of Notice that the amount of RAMRAM used by the used by the program is the same whether I use the template program is the same whether I use the template approach or write three separate functions.approach or write three separate functions.
What I’ve saved is having to What I’ve saved is having to type three separate type three separate functions into the source file. This makes the functions into the source file. This makes the listing shorter and easier to understand.listing shorter and easier to understand.
Also, if I want to Also, if I want to changechange the way the function the way the function works, I need to make the change in only one works, I need to make the change in only one place in the listing instead of three.place in the listing instead of three.
Function Templates with Function Templates with Multiple ArgumentsMultiple Arguments
Let’s look at another example of a function Let’s look at another example of a function template. This one takes Three arguments: template. This one takes Three arguments: two two template arguments and one basic typetemplate arguments and one basic type..
The purpose of this function is to search an The purpose of this function is to search an array for a specific value. array for a specific value.
The function returns the array index for that The function returns the array index for that value if it finds it, or -1 if it can’t find it.value if it finds it, or -1 if it can’t find it.
The The argumentsarguments are a pointer to the array, the are a pointer to the array, the value to search for, and the size of the array.value to search for, and the size of the array.
Function Templates with Function Templates with Multiple ArgumentsMultiple Arguments
// function returns index number of item, or -1 if not found // function returns index number of item, or -1 if not found templatetemplate
template <class template <class atypeatype>>int find(const int find(const atypeatype* array, * array, atypeatype value, int size)value, int size){{
for(int j=0; j<size; j++)for(int j=0; j<size; j++)if(array[ j ]==value) return j;if(array[ j ]==value) return j;
return -1;return -1;}}
char chrArr[ ] = {'a', 'c', char chrArr[ ] = {'a', 'c', 'f''f', 's', 'u', 'z'}; // array, 's', 'u', 'z'}; // arraychar ch = char ch = 'f''f'; // value to find; // value to findint intArr[ ] = {1, 3, 5, 9, 11, 13};int intArr[ ] = {1, 3, 5, 9, 11, 13};int in = int in = 66;;double dubArr[ ] = {1.0, 3.0, 5.0, 9.0, 11.0, 13.0};double dubArr[ ] = {1.0, 3.0, 5.0, 9.0, 11.0, 13.0};double db = double db = 4.04.0;;
Function Templates with Multiple Function Templates with Multiple ArgumentsArguments
int main()int main()
{{
cout << "\n 'f' in chrArray: index=" << find(chrArr, ch, 6);cout << "\n 'f' in chrArray: index=" << find(chrArr, ch, 6);
cout << "\n 6 in intArray: index=" << find(intArr, in, 6);cout << "\n 6 in intArray: index=" << find(intArr, in, 6);
cout << "\n 4 in dubArray: index=" << find(dubArr, db, 6);cout << "\n 4 in dubArray: index=" << find(dubArr, db, 6);
return 0;return 0;
}} Here, the name of the template argument is Here, the name of the template argument is atypeatype. The . The
compiler generates compiler generates three versions of the functionthree versions of the function, one for , one for each type used to call it.each type used to call it. OUTPUT:
'f' in chrArray: index=2 6 in intArray: index=-1 4 in dubArray: index=-1
Template Arguments Must Template Arguments Must MatchMatch
When a template function is invoked, all instances of the When a template function is invoked, all instances of the same template argument must be of the same type. For same template argument must be of the same type. For example, in example, in find()find(), if the array name is of type , if the array name is of type intint, the , the value to search for must also be of type value to search for must also be of type intint. You can’t say. You can’t say
int intarray[ ] = {1, 3, 5, 7}; // int arrayint intarray[ ] = {1, 3, 5, 7}; // int arrayfloat f1 = 5.0; // float valuefloat f1 = 5.0; // float valueint value = find(intarray, f1, 4); // errorint value = find(intarray, f1, 4); // error
Because the compiler expects all instances of Because the compiler expects all instances of atypeatype to be to be the same type. the same type.
find(int*, int, int); // It can generate a functionfind(int*, int, int); // It can generate a functionfind(int*, float, int); // It can’t generate a functionfind(int*, float, int); // It can’t generate a function
Because the first and second arguments must be the same type.Because the first and second arguments must be the same type.
Class TemplatesClass Templates
The template concept can be applied to The template concept can be applied to classes as well as to functions. classes as well as to functions.
Class templates are generally used for Class templates are generally used for data storage (container) classesdata storage (container) classes. .
Stacks and linked lists, are examples of Stacks and linked lists, are examples of data storage classes. data storage classes.
The Stack class in the program that is The Stack class in the program that is presented below, could store data only of presented below, could store data only of type int:type int:
Class TemplatesClass Templatesclass Stack {class Stack {
int st[MAX]; // array of intsint st[MAX]; // array of intsint top; // index number of top of stackint top; // index number of top of stack
public:public:Stack(); // constructorStack(); // constructorvoid push(int var); // takes int as argumentvoid push(int var); // takes int as argumentint pop(); // returns int valueint pop(); // returns int value
};}; If I wanted to store data of type long in a stack, I would need to define a If I wanted to store data of type long in a stack, I would need to define a
completely new class:completely new class:class LongStack {class LongStack {
long st[MAX]; // array of longslong st[MAX]; // array of longsint top; // index number of top of stackint top; // index number of top of stack
public:public:LongStack(); // constructorLongStack(); // constructorvoid push(long var); // takes long as argumentvoid push(long var); // takes long as argumentlong pop(); // returns long valuelong pop(); // returns long value
};};
Class TemplatesClass TemplatesSolution with a class template:Solution with a class template:template <class template <class TypeType>>class Stack{class Stack{
enum {MAX=100};enum {MAX=100};TypeType st[MAX]; // stack: array of any typest[MAX]; // stack: array of any typeint top; // number of top of stackint top; // number of top of stack
public:public:Stack(){top = 0;} // constructorStack(){top = 0;} // constructorvoid push(void push(TypeType ); // put number on stack); // put number on stackTypeType pop(); // take number off stackpop(); // take number off stack
};};template<class Type>template<class Type>
void void Stack<Stack<TypeType>>::push(::push(TypeType var) // put number on stack var) // put number on stack{{
if(top > MAX-1) // if stack full,if(top > MAX-1) // if stack full,cout<< "Stack is full!"; cout<< "Stack is full!";
st[top++] = var;st[top++] = var;}}
Class TemplatesClass Templates
template<class Type>template<class Type>
TypeType Stack< Stack<TypeType>>::pop() // take number off stack::pop() // take number off stack
{{
if(top <= 0) // if stack empty,if(top <= 0) // if stack empty,
cout<< "Stack is empty!"; cout<< "Stack is empty!";
return st[--top];return st[--top];
}}
Class TemplatesClass Templates
int main()int main()
{{
// s1 is object of class Stack<float>// s1 is object of class Stack<float>
Stack<Stack<floatfloat> > s1;s1;
// push 2 floats, pop 2 floats// push 2 floats, pop 2 floats
s1.push(1111.1);s1.push(1111.1);
s1.push(2222.2);s1.push(2222.2);
cout << "1: " << s1.pop() << endl;cout << "1: " << s1.pop() << endl;
cout << "2: " << s1.pop() << endl;cout << "2: " << s1.pop() << endl;
Class TemplatesClass Templates
// s2 is object of class Stack<long>// s2 is object of class Stack<long>
Stack<Stack<longlong> > s2;s2;
// push 2 longs, pop 2 longs// push 2 longs, pop 2 longs
s2.push(123123123L);s2.push(123123123L);
s2.push(234234234L);s2.push(234234234L);
cout << "1: " << s2.pop() << endl;cout << "1: " << s2.pop() << endl;
cout << "2: " << s2.pop() << endl;cout << "2: " << s2.pop() << endl;
return 0;return 0;
} // End of program} // End of program