You are on page 1of 274

C++ notes

Syllabus:
Chapter 1: Introduction to C++
Intro to C++, the main () function, Header files, Basic Input and Output (I/O) using
cin and cout, Variable, Constant.

Chapter 2: Operators
Operators-Arithmetic Operators, Assignment Operators, Relational Operators,
Logical Operators, Bitwise Operators, Other Operators, Operator Precedence.

Chapter 3: Conditional Statements


Control Statements-if, if...else and Nested if...else, switch. Case, break and continue

Chapter 4: Looping Statements


Loops-for loop, while loop, do while loop, goto.

Chapter 5: Arrays -1D array and 2D array

Chapter 6: Strings - Strings & String functions

Chapter 7: Functions
Function–Basics, call by value, call by reference & return by reference, Inline
function, overloading Functions, Recursive Functions

Chapter 8: Pointers - Pointers-Pointer, Dynamic Memory Allocation

Chapter 9: Classes, Encapsulation - Classes and Objects, public, private, protected,


Encapsulation

Chapter 10: Constructors


Constructors and destructors-Overloaded Constructor, Copy Constructor, Shallow
Copying Deep Copying.

Chapter 11: Friend Function


Overloading-this' Pointer, Structs vs Classes, Friends of a class, Operator Overloading
Chapter 12: Inheritance - Inheritance, Overloading vs overriding,
Chapter 13: Polymorphism - Polymorphism, Virtual Functions, Pure Virtual Functions
and AbstractClasses.

Chapter 14: Abstract Classes -- Abstract Classes as Interfaces

Chapter 15: Exception and File Handling - Exception, Files, Streams and I/O

Chapter 16: STL and Lambda Functions - STL, Generic Programming, Lambda Expression.
Chapter:1 Intro to C++

 Intro to C++
 Main () function
 Basic Input and Output (I/O) using
cin and cout
 Header files
 Tokens
Basics of C++
C ++ is an object-oriented programming language, C ++ was developed by Jarney
Stroustrup at AT & T Bell lab, USA in early eighties. C ++ was developed from c and Simula
67 language. C ++ was early called „C with classes.

C++ Comments:
C++ introduces a new comment symbol // (double slash). Comments start with a double
slash symbol and terminate at the end of line. A comment may start anywhere in the line and
whatever follows till the end of line is ignored. Note that there is no closing symbol.
The double slash comment is basically a single line comment. Multi line comments can
be written as follows:
// this is an example of
// c++ program
// thank you
The c comment symbols /* ….*/ are still valid and more suitable for multi-line comments.
/* this is an example of c++ program */

Output Operator:
The statement cout <<” Hello, world” displayed the string with in quotes on the screen.
The identifier cout can be used to display individual characters, strings and even numbers. It is
a predefined object that corresponds to the standard output stream. Stream just refers to a flow
of data and the standard Output stream normally flows to the screen display. The cout object,
whose properties are defined in iostream.h represents that stream. The insertion operator <<
also called the „put to‟ operator directs the information on its right to the object on its left.

Return Statement:
In C++ main () returns an integer type value to the operating system. Therefore, every
main () in C++ should end with a return (0) statement, otherwise a warning or an error might
occur.

Input Operator:
The statement cin>> number 1; is an input statement and causes. The program to wait
for the user to type in a number. The number keyed in is placed in the variable number1. The
identifier cin is a predefined object in C++ that corresponds to the standard input stream. Here
this stream represents the key board.
The operator >> is known as get from operator. It extracts value from the keyboard
and assigns it to the variable on its right.

Cascading Of I/O Operator:


cout<<”sum=”<<sum<<”\n”;
cout<<”sum=”<<sum<<”\n”<<”average=”<<average<<”\n”;
cin>>number1>>number2;

Structure Of a Program:
Probably the best way to start learning a programming language is by writing a
program. Therefore, here is our first program:
// my first program in C++
#include <iostream>
using namespace std;
int main ()
{
cout << "Hello World!";
return 0;
}
Output:-Hello World!
The first panel shows the source code for our first program. The second one shows the
result of the program once compiled and executed. The way to edit and compile a program
depends on the compiler you are using. Depending on whether it has a Development Interface
or not and on its version. Consult the compilers section and the manual or help included with
your compiler if you have doubts on how to compile a C++ console program.
The previous program is the typical program that programmer apprentices write for the
first time, and its result is the printing on screen of the "Hello World!" sentence. It is one of the
simplest programs that can be written in C++, but it already contains the fundamental
components that every C++ program has. We are going to look line by line at the code we have
just written:
// my first program in C++
This is a comment line. All lines beginning with two slash signs (//) are considered
comments and donot have any effect on the behavior of the program. The programmer can use
them to include short explanations or observations within the source code itself. In this case,
the line is a brief description of what our program is.

#include <iostream>
Lines beginning with a hash sign (#) are directives for the preprocessor. They are not
regular code lines with expressions but indications for the compiler's preprocessor. In this case
the directive #include<iostream> tells the preprocessor to include the iostream standard file.
This specific file (iostream) includes the declarations of the basic standard input-output library
in C++, and it is included because its functionality is going to be used later in the program.

using namespace std;


All the elements of the standard C++ library are declared within what is called a
namespace, the namespace with the name std. So in order to access its functionality we declare
with this expression that we will be using these entities. This line is very frequent in C++
programs that use the standard library, and in fact it will be included in most of the source
codes included in these tutorials.
Main () function
int main ()
This line corresponds to the beginning of the definition of the main function. The main
function is the point by where all C++ programs start their execution, independently of its
location within the source code. It does not matter whether there are other functions with other
names defined before or after it – the instructions contained within this function's definition
will always be the first ones to be executed in any C++ program. For that same reason, it is
essential that all C++ programs have a main function.
The word main is followed in the code by a pair of parentheses (()). That is because it
is a function declaration: In C++, what differentiates a function declaration from other types of
expressions are these parentheses that follow its name. Optionally, these parentheses may
enclose a list of parameters within them.
Right after these parentheses we can find the body of the main function enclosed in
braces ({}). What is contained within these braces is what the function does when it is executed.

cout << "Hello World!";


This line is a C++ statement. A statement is a simple or compound expression that can
actually produce some effect. In fact, this statement performs the only action that generates a
visible effect in our first program. cout represents the standard output stream in C++, and the
meaning of the entire statement is to insert a sequence of characters (in this case the Hello
World sequence of characters) into the standard output stream (which usually is the screen).
cout is declared in the iostream standard file within the std namespace, so that's why
we needed to include that specific file and to declare that we were going to use this specific
namespace earlier in our code.
Notice that the statement ends with a semicolon character (;). This character is used to
mark the end of the statement and in fact it must be included at the end of all expression
statements in all C++ programs (one of the most common syntax errors is indeed to forget to
include some semicolon after a statement).
return 0;
The return statement causes the main function to finish. return may be followed by a
return code (in our example is followed by the return code 0). A return code of 0 for the main
function is generally interpreted as the program worked as expected without any errors during
its execution. This is the most usual way to end a C++ console program.
You may have noticed that not all the lines of this program perform actions when the
code is executed. There were lines containing only comments (those beginning by //). There
were lines with directives for the compiler's pre-processor (those beginning by #). Then there
were lines that began the declaration of a function (in this case, the main function) and, finally
lines with statements (like the insertion into cout), which were all included within the block
delimited by the braces ({}) of the main function.
The program has been structured in different lines in order to be more readable, but in
C++, we do not have strict rules on how to separate instructions in different lines. For example,
instead of
int main ()
{
int a;
cin>>a;
cout<<a;
cout << " Hello World!";
return 0;
}
Input:10
Output:
10 Hello World!
All in just one line and this would have had exactly the same meaning as the
previous code. In C++, the separation between statements is specified with an ending
semicolon (;) atthe end of each one, so the separation in different code lines does not
matter at all for this purpose. We can write many statements per line or write a single
statement that takes many code lines. The division of code in different lines serves
only to make it more legible and schematic for the humans that may read it.

Let us add an additional instruction to our first program:


// my second program in C++
#include <iostream>
using namespace std;
int main ()
{
cout << "Hello World! ";
cout << "I'm a C++ program";
return 0;
}
Output:-Hello World! I'm a C++ program
In this case, we performed two insertions into cout in two different statements. Once
again, the separation in different lines of code has been done just to give greater readability to
the program, since main could have been perfectly valid defined this way:
int main ()
{
cout << " Hello World! ";
cout << " I'm a C++ program ";
return 0;
}
We were also free to divide the code into more lines if we considered it more convenient:
int main ()
{
cout << "Hello World!";
cout << "I'm a C++ program";
return 0;}

And the result would again have been exactly the same as in the previous examples.
Header files
Preprocessor directives:
Preprocessor directives (those that begin by #) are out of this general rule since they are not
statements. They are lines read and processed by the preprocessor and do not produce any code
by themselves. Preprocessor directives must be specified in their own line and do not have to
end with a semicolon (;).

STRUCTURE OF C++ PROGRAM


Include files
Class declaration
Class functions, definition
Main function program
Example :-
# include<iostream.h>
class person
{
char name[30];
int age;
public:
void getdata(void);
void display(void);
};
void person :: getdata ( void )
{
cout<<”enter name”;
cin>>name;
cout<<”enter age”;
cin>>age;
}
void display()
{
cout<<”\n name:”<<name;
cout<<”\n age:”<<age;
}
int main( )
{
person p;
p.getdata();
p.display();
return(0);
}
Tokens
TOKENS:
The smallest individual units in program are known as tokens. C++ has the following
tokens.
i. Keywords
ii. Identifiers
iii. Constants
iv. Strings
v. Operators
KEYWORDS:
The keywords implement specific C++ language feature. They are explicitly reserved
identifiers and can‟t be used as names for the program variables or other user defined program
elements. The keywords not found in ANSI C are shown in red letter.

C++ KEYWORDS:
Asm double new switch
Auto else operator template
Break enum private this
Case extern protected throw
Catch float public try
Char for register typedef
Class friend return union
Const goto short unsigned
Continue if signed virtual
Default inline sizeof void
Delete long struct while

IDENTIFIERS:
Identifiers refers to the name of variable, functions, array, class etc. created by
programmer. Each language has its own rule for naming the identifiers.

The following rules are common for both C and C++.


1. Only alphabetic chars, digits and underscore are permitted.
2. The name can‟t start with a digit.
3. Upper case and lower-case letters are distinct.
4. A declared keyword can‟t be used as a variable name.
In ANSI C the maximum length of a variable is 32 chars but in c++ there is no bar.
BASIC DATA TYPES IN C++

Both C and C++ compilers support all the built in types. With the exception of void the
basic datatypes may have several modifiers preceding them to serve the needs of various
situations. The modifiers signed, unsigned, long and short may applied to character and integer
basic data types. However the modifier long may also be applied to double.

Data types in C++ can be classified under various categories.


The type void normally used for:
1) To specify the return type of function when it is not returning any value.
2) To indicate an empty argument list to a function.
Example:
Void function(void);

Another interesting use of void is in the declaration of genetic pointer


Example:
Void *gp;
Assigning any pointer type to a void pointer without using a cast is allowed in both C
and ANSI C. In ANSI C we can also assign a void pointer to a non-void pointer without using
a cast to non-void pointer type. This is not allowed in C ++.
Example:
void *ptr1;
void *ptr2;
Are valid statement in ANSI C but not in C++. We need to use a cast
operator.
ptr2=(char * ) ptr1;
USER DEFINED DATA TYPES:
STRUCTERS AND CLASSES
We have used user defined data types such as struct, and union in C. While these more
features have been added to make them suitable for object-oriented programming. C++ also
permits us to define another user defined data type known as class which can be used just like
any other basic data type to declare a variable. The class variables are known as objects, which
are the central focus of oops.

SYMBOLIC CONSTANT:
There are two ways of creating symbolic constants in c++.
1. using the qualifier const.
2. defining a set of integer constants using enum keywords.
In both C and C++, any value declared as const can‟t be modified by the program in
any way. In C++, we can use const in a constant expression. Such as
const int size = 10;
char name (size);
This would be illegal in C. const allows us to create typed constants instead of having
to use #defme to create constants that have no type information.
const size=10;
Means
const int size =10;
C++ requires a const to be initialized. ANSI C does not require an initializer, if none is given,
it initializes the const to 0. In C++ const values are local and in ANSI C const values are global.
However, they can be made local made local by declaring them as static. In C++ if we want to
make const value as global then declare as extern storage class.
Ex: external const total=100; Another method
of naming integer constants is as follows: -
enum {x,y,z};
DECLARATION OF VARIABLES:
In ANSIC C all the variable which is to be used in programs must be declared at the
beginning of the program. But in C++ we can declare the variables any who‟s in the program
where it requires. This makes the program much easier to write and reduces the errors that may
be caused by having to scan back and forth. It also makes the program easier to understand
because the variables are declared in the context of their use.

Example:

main()
{
float x,average;float sum=0;
24 P.T.O for(int i=1;i<5;i++)
{
cin>>x; sum=sum+x
}
float average; average=sum/x;
cout<<average;
}

REFERENCE VARIABLES:
C++interfaces a new kind of variable known as the reference variable. A references
variable provides an alias.(alternative name) for a previously defined variable. For example ,if
we make the variable sum a reference to the variable total, then sum and total can be used
interchangeably to represent the variable.

A reference variable is created as follows:


Synatx: Datatype & reference –name=variable name;

Example:
floattotal=1500;
float &sum=total;
Here sum is the alternative name for variables total, both the variables refer to the same data
object in the memory. A reference variable must be initialized at the time of declaration. Note
that C++ assigns additional meaning to the symbol & here & is not an address operator. The
notation float & means reference to float.
Example:
int n[10];
int &x=n[10];
char &a=‟\n‟;
Chapter:2 Operators
 Arithmetic Operators
 Assignment Operators
 Relational Operators
 Logical Operators
 Bitwise Operators
 Other Operators
 Operator Precedence.
Operators in C++
An operator is a symbol that tells the compiler to perform specific mathematical or logical
manipulations. C++ is rich in built-in operators and provide the following types of operators −
Arithmetic Operators
Relational Operators
Logical Operators
Bitwise Operators
Assignment Operators
Misc Operators
This chapter will examine the arithmetic, relational, logical, bitwise, assignment and other operators
one by one.

Arithmetic Operators
There are following arithmetic operators supported by C++ language −
Assume variable A holds 10 and variable B holds 20, then −

Show Examples

Operator Descriiptiion Examplle

+ Adds two operands A + B will give 30

- Subtracts second operand from the first A - B will give -10

* Multiplies both operands A * B will give 200

/ Divides numerator by de-numerator B / A will give 2

% Modulus Operator and remainder of after B % A will give 0


an integer division

++ Increment operator , increases integer A++ will give 11


value by one

-- Decrement operator , decreases integer A-- will give 9


value by one
Relational Operators
There are following relational operators supported by C++ language
Assume variable A holds 10 and variable B holds 20, then −
Show Examples

Operator Descriiptiion Examplle

== Checks if the values of two operands are (A == B) is not true.


equal or not, if yes then condition
becomes true.

!= Checks if the values of two operands are (A != B) is true.


equal or not, if values are not equal then
condition becomes true.

> Checks if the value of left operand is (A > B) is not true.


greater than the value of right operand, if
yes then condition becomes true.

< Checks if the value of left operand is less (A < B) is true.


than the value of right operand, if yes then
condition becomes true.

>= Checks if the value of left operand is (A >= B) is not true.


greater than or equal to the value of right
operand, if yes then condition becomes
true.

<= Checks if the value of left operand is less (A <= B) is true.


than or equal to the value of right operand,
if yes then condition becomes true.

Logical Operators
There are following logical operators supported by C++ language.
Assume variable A holds 1 and variable B holds 0, then −

Show Examples
Operator Descriiptiion Examplle

&& Called Logical AND operator. If both the (A && B) is false.


operands are non-zero, then condition
becomes true.

|| Called Logical OR Operator. If any of the (A || B) is true.


two operands is non-zero, then condition
becomes true.

! Called Logical NOT Operator. Use to !(A && B) is true.


reverses the logical state of its operand. If
a condition is true, then Logical NOT
operator will make false.

Bitwise Operators
Bitwise operator works on bits and perform bit-by-bit operation. The truth tables for &, |, and ^ are
as follows −

p q p&q p || q p^q

0 0 0 0 0

0 1 0 1 1

1 1 1 1 0

1 0 0 1 1

Assume if A = 60; and B = 13; now in binary format they will be as follows −
A = 0011 1100

B = 0000 1101

A&B = 0000 1100


A|B = 0011 1101
A^B = 0011 0001

~A = 1100 0011
The Bitwise operators supported by C++ language are listed in the following table. Assume variable
A holds 60 and variable B holds 13, then −

Show Examples
Operator Descriiptiion Examplle

& Binary AND Operator copies a bit to the


(A & B) will give 12 which is 0000 1100
result if it exists in both operands.

| Binary OR Operator copies a bit if it exists (A | B) will give 61 which is 0011 1101
in either operand.

^ Binary XOR Operator copies the bit if it is


(A ^ B) will give 49 which is 0011 0001
set in one operand but not both.

~ Binary Ones Complement Operator is (~A ) will give -61 which is 1100 0011 in
unary and has the effect of 'flipping' bits. 2's complement form due to a signed
binary number.

<< Binary Left Shift Operator. The left


operands value is moved left by the
A << 2 will give 240 which is 1111 0000
number of bits specified by the right
operand.

>> Binary Right Shift Operator. The left


operands value is moved right by the
A >> 2 will give 15 which is 0000 1111
number of bits specified by the right
operand.

Assignment Operators

There are following assignment operators supported by C++ language −


Show Examples
Operator Descriiptiion Examplle

= Simple assignment operator, Assigns values C = A + B will assign value of A + B


from right side operands to left side operand. into C

+= Add AND assignment operator, It adds right


operand to the left operand and assign the C += A is equivalent to C = C + A
result to left operand.

-= Subtract AND assignment operator, It


subtracts right operand from the left operand C -= A is equivalent to C = C - A
and assign the result to left operand.

*= Multiply AND assignment operator, It


multiplies right operand with the left operand C *= A is equivalent to C = C * A
and assign the result to left operand.

/= Divide AND assignment operator, It divides


left operand with the right operand and C /= A is equivalent to C = C / A
assign the result to left operand.

%= Modulus AND assignment operator, It takes


modulus using two operands and assign the C %= A is equivalent to C = C % A
result to left operand.

<<= Left shift AND assignment operator. C <<= 2 is same as C = C << 2

>>= Right shift AND assignment operator. C >>= 2 is same as C = C >> 2

&= Bitwise AND assignment operator. C &= 2 is same as C = C & 2

^= Bitwise exclusive OR and assignment


C ^= 2 is same as C = C ^ 2
operator.

|= Bitwise inclusive OR and assignment


C |= 2 is same as C = C | 2
operator.

Misc Operators
The following table lists some other operators that C++ supports.
Sr..No Operator & Descriiptiion

1
siizeof
sizeof operator returns the size of a variable. For example, sizeof(a), where ‘a’ is
integer, and will return 4.

2
Condiitiion ? X : Y
Conditional operator (?) . If Condition is true then it returns value of X otherwise
returns value of Y.

3
,,
Comma operator causes a sequence of operations to be performed. The value of the
entire comma expression is the value of the last expression of the comma-separated list.

4
.. (dot) and -> (arrow)
Member operators are used to reference individual members of classes, structures,
and unions.

5 Cast

Casting operators convert one data type to another. For example, int(2.2000) would
return 2.

6 &
Pointer operator & returns the address of a variable. For example &a; will give actual
address of the variable.

7 *

Pointer operator * is pointer to a variable. For example *var; will pointer to a variable
var.

Operators Precedence in C++


Operator precedence determines the grouping of terms in an expression. This affects how an
expression is evaluated. Certain operators have higher precedence than others; for example, the
multiplication operator has higher precedence than the addition operator −
For example x = 7 + 3 * 2; here, x is assigned 13, not 20 because operator * has higher
precedence than +, so it first gets multiplied with 3*2 and then adds into 7.

Here, operators with the highest precedence appear at the top of the table, those with the lowest
appear at the bottom. Within an expression, higher precedence operators will be evaluated first.
Show Examples

Category Operator Associiatiiviity

Postfix () [] -> . ++ - - Left to right

Unary + - ! ~ ++ - - (type)* & sizeof Right to left

Multiplicative */% Left to right

Additive +- Left to right

Shift << >> Left to right

Relational < <= > >= Left to right

Equality == != Left to right

Bitwise AND & Left to right

Bitwise XOR ^ Left to right

Bitwise OR | Left to right

Logical AND && Left to right

Logical OR || Left to right

Conditional ?: Right to left

Assignment = += -= *= /= %=>>= <<= &= ^= |= Right to left

Comma , Left to right


Chapter:3 Conditional Statements
 if, if...else
 Nested if...else
 Jump statement
 Switch Case
Control Structures or Conditional Statements
A program is usually not limited to a linear sequence of instructions. During its process,
it may bifurcate, repeat code or take decisions. For that purpose, C++ provides control
structures that serve to specify what has to be done by our program, when and under which
circumstances.
With the introduction of control structures, we are going to have to introduce a new
concept: the compound- statement or block. A block is a group of statements which are
separated by semicolons (;) like all C++ statements, but grouped together in a block enclosed
in braces: { }:
{ statement1; statement2; statement3; }
Most of the control structures that we will see in this section require a generic statement,
as part of its syntax. A statement can be either a simple statement (a simple instruction ending
with a semicolon) or a compound statement (several instructions grouped in a block), like the
one just described. In the case that we want the statement to be a simple statement, we do not
need to enclose it in braces ({}). But in the case that we want the statement to be a compound
statement it must be enclosed between braces ({}), forming a block.

Conditional structure
Conditional structure contain three types of write conditional programs.
1. IF – statements
2. IF – Else statements
3. IF – Else – IF statements
IF – Statements
IF- keyword: it is used to execute a statement or block only if a condition is
fulfilled. Its form is:
if (condition) statement
Where condition is the expression that is being evaluated. If this condition is true,
statements executed. If it is false, statements ignored (not executed) and the program continues
right after this conditional structure.
The structure of execution the statements is as flowchart blow:

Ex: The following code fragment prints x is 100only if the value stored in the x variable is
indeed 100:
if (x == 100)
cout << "x is 100";
If we want more than a single statement to be executed in case that the condition is true we can
specify a block using braces { }:
if (x == 100)
{
cout << "x is ";
cout << x;
}
Ex: Write a C++ program to enter two Boolean numbers then, print phrase "A And B"
if A and B equal to 1, or print phrase "A Or B" if A equal to 1 and B equal to 0.
#include <iostream>
using namespace std;
int main ()
{
bool A,B;
cin >>A ;
cin >>B ;
if ((A==1)&&(B==1))
{
cout << "A And B"<<'\n';
}
if ((A==1)||(B==0))
{ cout << "A or B"<<'\n';
}
return 0;
}

IF – Else statements
We can additionally specify what we want to happen if the condition is not fulfilled by
using the keyword else. Its form used in conjunction with ifis:
If (condition)
statement1
else
statement2
Prints on the screen x is 100if indeed has a value of 100, but if it has not -and
only if not- it prints out x is not 100.
The (if – else)structures can be concatenated with the intention of verifying a
range of values.
Chapter Four – conditional statements
Ex:
if (x == 100)
cout << "x is 100";
else
cout << "x is not 100";

Ex: Write a C++ program to find a solution for the following equation:
Enter (X and Y) and print Z then display the message "Wrong Values", if the two
conditions above are not satisfied.
Sol:
#include <iostream>
using namespace std;
int main ()
{
float X, Y;
float Z;
cin >> X;
cin>>Y;
if ((X + Y) >= 0)
{if (X > 0)
Z = (sqrt (X + Y)) / X ;
cout << "The value of Z is:"<< Z;
}
else
{cout << "Wrong Values";
}
return 0;
}
*Remember that in case that we want more than a single statement to be executed, we must
group them in a block by enclosing them in braces { }.
IF – Else – IF statements
The If and If-else statement is great when you must test against more than two
conditions, however, the If and If-else becomes difficult to maintain. Although the logic of the
If-else statement is simple, the coding is extremely difficult to follow. C++ language supports
a statement, called If-else-If, which handles such multiple-choice conditions better than If-else.
Here is the format of the If-else-If statement and also its
flowchart shown in figure below:
If (Condition-1)
Comment-1;
else If (Condition-2)
Comment -2;
.
.
.
else If (Condition-n)
Comment-n;
else
Any Comment;
Jump statements.
Jump statements divided to three statements:
1. The break statement
2. The continue statement
3. The goto statement

The break statement

Using break we can leave a loop even if the condition for its end is not fulfilled.
It can be used to end an infinite loop, or to force it to end before its natural end. The conditional
statements break statement must be used with switch case (selective statement) or with loops.
Therefore, we will discuss this statement with switch statement.

The continue statement

The continue statement causes the program to skip the rest of the loop in the
current iteration as if the end of the statement block had been reached, causing it to
jump to the start of the following iteration. The continue statement example will
contain loop. Therefore, we will discuss this statement in the next chapter.

The goto statement


goalpost make an absolute jump to another point in the program. You should
use this feature with caution since its execution causes an unconditional jump ignoring
any type of nesting limitations. The destination point is identified by a label, which is then used
as an argument for the goto statement. A label is made of a valid identifier followed by a colon
(:).
This instruction has no concrete use in structured or object-oriented programming
aside from those that low-level programming fans may find for it.
Ex: Write C++ program to make countdown loop using goto statement.
Sol:
#include <iostream>
using namespace std;
int main ()
{
int n, b;
n=10;
b: n--;
cout << n << ", ";
if (n==0)
{ return 0;}
goto b;
}
The selective statement (switch statement)
The switch statement objective is to check several possible constant values for
an expression. Something similar to what we did at the beginning of this section with
the concatenation of several if and else if instructions. Its form as the following:
switch (expression)
{
case constant1:
group of statements 1; break;
case constant2:
group of statements 2;break;
.
.
.
default:
default group of statements
}

#include <iostream>
using namespace std;
int main ()
{
int n;
cin >> n;
switch (n)
{case 0:
cout<< "Baghdad";
break;
case 1:
cout<< "Berlin";break;
case 2:
cout<< "Beirut";break;
case 3:
cout<< "Cairo";break;
defoult:
cout<< "Paris";break;
}
return 0;
}
Chapter:4 Looping Statements
 For loop
 While loop
 do while loop
 goto
Loops are generally used when a block of code needs to be executed repeatedly. It
consists of a sequence of code that is executed and repeated until a specific condition is
achieved.

For example, if you would like to write a program that prints the word “Hello” 5 times,
there are two ways to do it, either by writing 5 print statements or by using loops as can be seen
in the next code snippet.

Alternative 1

#include
<iostream> using
namespace std;

int main()
{
cout << "Hello" <<
endl; cout << "Hello"
<< endl; cout <<
"Hello" << endl; cout
<< "Hello" << endl;
cout << "Hello" <<
endl;

return 0;
}

Output:

Hello

Hello

Hello

Hello

Hello
Alternative 2

#include <iostream>
using namespace std;

int main()
{
for(int i=0; i<5; i++)
{
cout << "Hello" << endl;
}

return 0;
}

Output:

Hello

Hello

Hello

Hello

Hello

As you can see, both methods have exactly the same output. However, as your program
gets more complex, for example if you want to print the word “Hello” 1000 times this time,
writing 1000 print statements would not be wise or efficient.

For Loops

The for loop is typically used when you know exactly how many times or iterations
should be executed. Generally, it enables you to execute your block K number of times using
just one line of code.

Syntax

for (initialize iterator; end condition; iterator update)


{
// block of code to execute
}
In for loops, the iterator or loop variable is used to control your loop. In other words, it
is used as your counter, you choose what to do with it at each iteration (increment it or
decrement by a certain amount) and finally decide when to end your loop when a specific
condition is reached.

Example

Write a program that initializes an empty vector of integers and then fill it with numbers
from 1 to 5000 using for loop.

Here we want to initialize the loop counter “i”, increment the counter with 1 at each
iteration and pass it to the vector, and finally when the counter reaches 5000 breaks from the
loop.

#include <iostream>
#include <vector>

using namespace std;

int main()
{
vector<int> my_vect;
for(int i=1; i<=5000; i++)
{
my_vect.push_back(i);
}

return 0;
}

Now we have executed a block of code 5000 times using only one code statement.
While Loops

The difference between while and for loops is that this time you only need the end
condition. This means, you need to handle the initialization of your iterator and incrementing
or decrementing it separately and independent from the loop control statement.

Syntax

while (end condition)


{
// block of code to execute
}
Example

Write a program that initializes an empty vector of integers and then fills it with numbers from
1 to 5000 using while loop.

Here we are going to implement the same program as in the loop however this time using while
loop.

#include <iostream>
#include <vector>

using namespace std;


int main()
{
vector<int> my_vect;
int i=1;

while(i<=5000)
{
my_vect.push_back(i);
i++;
}

return 0;
}

Note that in both examples, the for and while loops, you can choose to inversely loop
from a greater to a smaller value and you can also increment your iterator using different values
other than 1.

Example

Write a program that initializes an empty vector, fills it with only even numbers from
5000 to 1 using for loop.

Here we need to inversely loop from 5000 to 1 and decrement our iterator with value 2 to get
only even numbers.
#include <iostream>
#include <vector>
using namespace std;

int main()
{
vector<int> my_vect;
for(int i=5000; i>=1; i-=2)
{
my_vect.push_back(i);
}

return 0;
}
Do While Loop

The do-while loop is very similar to the while loop. However, in the do-while loop, the
block of code is executed first before checking the end statement.

Syntax

do
{
// execute block of code
}
while (end condition);
Also, note that here we add a semicolon “;” at the end of the loop.

Example

Write a program to manually print characters in a string until the space character is found then
the loop terminates.

#include <iostream>
#include <string>
using namespace std;

int main()
{
string hello = "Hello World!";
cout << "Original String: " << endl;
cout << "New String: ";

int i=0;
do
{
cout << hello[i];
i++;
}
while (hello[i] != ' ');

cout << endl;


return 0;
}

Output:
Original String: Hello World!

New String: Hello

Infinite Loops

Infinite loops are used when you need to execute a block of code forever and are
typically used with embedded systems applications. On the other hand, they can be used for
normal day to day applications and can normally be interrupted using break statements.

There are 2 ways to write infinite loops.

Method 1

Writing an empty for loop control statement.

for(;;)
{
// run forever
}

Method 2

Using and always TRUE condition with while loops.

while (true)
{
// run forever
while (1)
{
// run forever
}
}

Example
Write a program that runs infinitely until and reads input characters from the user until
the key button is hit. Definitely a better way to do this is using the getline function
“std::getline(cin, line);”. However, an infinite loop is used here just for illustration.
#include <iostream>
#include <string>
#include <vector>
using namespace std;

int main()
{
string myStr;
char c;

cin >> std::noskipws;


while (cin >> c && c != '\n')
{
myStr.push_back(c);
}

cout << myStr << endl;


return 0;
}

Range-based For Loops

Range-based for loops were introduced starting C++ 11. In this type of loops, we do
not rely on counting values in our structure but instead, we loop over a range.

For example, if you have a vector of integers, instead of creating a counter and then
using this counter at each iteration to access an element in the vector, a range-based for loop
would allow you to directly get that element without needing to count.

Example

Write a program that loops over a string and print “Found it” when character “W” is found
(upper or lower case), print the index where it found it.
#include <iostream>
#include <string>

using namespace std;

int main()
{
string hello = "Welcome to the world wide web";
int index = 0;

for (char c: hello)


{
if ( (c == 'W') || (c == 'w') )
{
cout << "Found it at index: " << index << endl;
}
index++;
}

return 0;
}

Output:

Found it at index: 0

Found it at index: 15

Found it at index: 21

Found it at index: 26

Alternatively, range-based loops can be used more generically if you do not the type of
iterator or what you are looping over by using the type inference “auto” in C++11.

Example

Write a program that initializes a vector and a string then loop over both and prints their
elements.
#include <iostream> #include
<string> #include <vector>
using namespace std;

int main()
{
string myStr = "Hello World!"; vector <int>
myVect = {1,2,3,4,5};

for(auto element: myStr)


{
cout << element;
}
cout << endl;

for(auto element: myVect)


{
cout << element;
}
cout << endl;

return 0;
}
Output:

Hello World!

12345

“for_each” Loop in C++11

This one is similar in concepts to the looping techniques that we‟ve discussed
previously. However, here you are able to pass functions to the loop statement.

Note that this time you need to include one extra header:

#include <algorithm>
Syntax

for_each (InputIterator start, InputIterator end, Function fn)

This line can be interpreted to, for each element in memory from “start” iterator to
“end” iterator, call the function “fn” and pass it the current iterator.

Example

Write a program that initializes an array of 10 integers, write a function that takes one integer
as argument and prints it and then finally loops the array and print its elements using
“for_each”.
#include <iostream>
#include <algorithm>
using namespace std;

void printNum(int num)


{
cout << num << endl;
}

int main()
{
int myArray[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

for_each(myArray, myArray + 10, printNum);

return 0;
}
Output:

10

Here we used the start iterator as the first element in the array and the end iterator as
the start iterator plus the size or number of iterations needed. Also, note that functions used
need to be of type void.
GOTO

Transfers control unconditionally.


Used when it is otherwise impossible to transfer control to the desired location using
other statements.

Syntax

goto label ;

Explanation
The goto statement transfers control to the location specified by label. The goto
statement must be in the same function as the label it is referring, it may appear before or after
the label.
If transfer of control exits the scope of any automatic variables (e.g. by jumping
backwards to a point before the declarations of such variables or by jumping forward out of a
compound statement where the variables are scoped), the destructors are called for all variables
whose scope was exited, in the order opposite to the order of their construction.
The goto statement cannot transfer control into a try-block or into a catch-clause, but
can transfer control out of a try-block or a catch-clause (the rules above regarding automatic
variables in scope are followed)
If transfer of control enters the scope of any automatic variables (e.g. by jumping
forward over a declaration statement), the program is ill-formed (cannot be compiled), unless
all variables whose scope is entered have
1) scalar types declared without initializers
2) class types with trivial default constructors and trivial destructors initializers
3) cv-qualified versions of one of the above
4) arrays of one of the above
(Note: the same rules apply to all forms of transfer of control)

Keywords
goto

Notes
In the C++ programming language, the goto statement has fewer restrictions and can
enter the scope of any variable other than variable-length array or variably-modified pointer.
Example
#include <iostream>

struct Object {
// non-trivial destructor
~Object() { std::cout << "d"; }
};

struct Trivial {
double d1;
double d2;
}; // trivial ctor and dtor

int main()
{
int a = 10;

// loop using goto


label:
Object obj;
std::cout << a << " ";
a = a - 2;

if (a != 0) {
goto label; // jumps out of scope of obj, calls obj destructor
}
std::cout << '\n';

// goto can be used to leave a multi-level loop easily


for (int x = 0; x < 3; x++) {
for (int y = 0; y < 3; y++) {
std::cout << "(" << x << ";" << y << ") " << '\n';
if (x + y >= 3) {
goto endloop;
}
}
}
endloop:
std::cout << '\n';

goto label2; // jumps into the scope of n and t


int n; // no initializer
Trivial t; // trivial ctor/dtor, no initializer
// int x = 1; // error: has initializer
// Object obj2; // error: non-trivial dtor
label2:

{
Object obj3;
goto label3; // jumps forward, out of scope of obj3
}
label3:
std::cout << '\n';
}
Output:
10 d8 d6 d4 d2
(0;0)
(0;1)
(0;2)
(1;0)
(1;1)
(1;2)

d
d
Chapter:5 Arrays
 1D array
 2D array
1D array
One dimensional array are the simplest form of an array in C++ language. You can
easily declare, initialize, and manipulate a one-dimensional array. A one-dimensional array can
be a parameter for function and so on. You can treat individual array element like any other
C++ variables.
1-D Array Declaration
The syntax to declare a one-dimensional array is very simple. Here it is,
<datatype> <array name> [n];
The two square brackets hold the number of elements in the array denoted by n.

Example#1
float demo [10];
The above array can hold 11 elements because the index associated with each array
element starts with 0. The first element has an index value of 0.

1-D Array Initialization


There are different ways to initialize an array. You must provide values to each array
element before using them in your program.

The syntax to initialize a one-dimensional array is as follows.


<data_type> <array_name> [n]; //array declaration first
<array_name> [n] = {<array_value1, array_value2, ..., array_value n-1}; //value
assignment
or
<data_type> <array_name> [n] = {<arrayvalue , array_value2 , ... , array_value n-1};

You can use any suitable method given. Here is an example for one-dimensional array
declaration.

Example #2
int toyota_car [5]; //array declaration
toyota_car [5]= { 2345, 4566, 7766, 3456, 9898}; //array value assignment
Example #3
char superheroes[3] = {"spiderman", "superman", "ironman"};
or
you can do the declaration and assignment without specifying a number. See the
example below.

Example #4
char superheroes[] = {"spiderman", "superman", "ironman"};
In the above example, we never provide any number to the subscript, the assignment of
3 values will determine the length of the one-dimensional array.

How To Pass An Array In A Function


The size of the one-dimensional array is large and it is difficult to pass an entire array
as a function parameter. This will crash the memory or slow down the program. However,
arrays are different than normal variables, they are like pointers, a variable that refers to another
variable instead of holding value. Only some characteristics of pointers are adopted by arrays.

The first element of the array has an index value of 0. If you use the name of the array,
then it refers to the memory address of the first element of the array. Using the first element,
you can find the memory address of rest of the elements and this is done by adding an offset to
the memory address of the first element.

For example,

arrayT has address 0x256778, then


arrayT + 1 has the address of the next location, and so on.
*(arrayT+ 1) gives the value stored at the next location. See the image below for better
understanding.
Array Index and Value

Therefore, to pass an array as a function parameter, you need to pass only the first
element memory address and the rest of the array can be calculated automatically.

Function Declaration with Array as Parameter


You must declare a function as usual and declare the array as a parameter for the
function. Check the example below.

int calculate_sum(int arrayT[]); //function declaration


Note that we have not specified a number for the subscript. You can do it separately.

Function Definition With Array as Parameter


Function definition must contain the array with type as a parameter.
int calculate_sum(int arrayT[])
{
Some code;
}
Function Call with Array as Argument
The function call is the most important part that contains the actual argument. Here you
must pass only the first element memory address and any other values for the function.
int calculate_sum(arrayT);
The following example program demonstrates the concept.

Example Program:
/* This program demonstrate the use of memory address of the first element of an array and
pass it as a parameter to a function.
The function use a different subscript notation (a + i) to compute sum of all elements of the
array */

#include <cstdlib>
#include <iostream>
using namespace std;
int main()
{
int arr[5]={23,45,67,112,22};
int arrpara(int arr[]);
arrpara(arr);
system("PAUSE");
return EXIT_SUCCESS;
}
int arrpara(int arr[])
{
int sum = 0;
int i;
for(i=0;i<5;i++)
{
sum = sum + *(arr + i);
}
cout << " first element =" << " " << arr << endl;
cout << "sum =" << " " << sum << endl;
}
Output:

first element = 0x28ff20


sum = 269
2D array or multidimensional array
A C++ multidimensional array has more dimensions identified by the number of
subscripts. In this article, you will learn about a two-dimensional array in detail.

Two-dimensional Array
A two-dimensional array has rows and columns. The horizontal arrangement of
elements within a two-dimensional array is row and vertical arrangement is a column.
For example,
A[2][4] means that this two-dimensional element is from 3rd row and 5th column. The
row or column index starts at 0.

Two-dimensional Array Declaration


To declare a 2d array like any variable does the following.
<data_type><array_name>[m][n];
The ism no of rows and equalsn no of columns.

Example #1
int account [3][4];
float boxes[2][3];
The example shows that the array account has 3 rows and 4 columns indicated by
subscripts.

Two-dimensional Array Initialisation


Initialising two-dimensional array means assigning initial values. There are two ways
to do that.

Consider following examples,


int matrix [3][3];
matrix [3][3] = {5,6,8,1,4,7,9,2,0};
First, note that the total number of values are equal to 3 × 3 – rows X columns.
int bins[2][2];
bins[2][2] = {{23, 45},{78, 43}};
The first internal brace is the first row and never changes. Similarly, the second brace
is the second row.

Also, you can initialise 2a d array dynamically. See the example program below.

#include <cstdlib>
#include <iostream>
using namespace std;
int main()
{
int sq_matrix[3][3];
int i,j;
//Reading values for matrix
cout << "Enter matrix values";
for(i =0;i<3;i++)
{
for(j=0;j<3;j++)
{
cin >> sq_matrix [i][j];
}
}
//print the array
for(i =0;i<3;i++)
{
for(j=0;j<3;j++)
{
cout << sq_matrix [i][j] << " ";
}
cout << endl;
}
system("PAUSE");
return EXIT_SUCCESS;
}
Output

Enter matrix values4


8
9
0
8
4
2
9
7
489
084
297
Chapter:6 Strings

 Strings & String functions


String Class in C++
The standard C++ library provides a string class type that supports all the operations mentioned
above, additionally much more functionality. We will study this class in C++ Standard Library
but for now let us check following example:

At this point, you may not understand this example because so far we have not discussed Classes
and Objects. So can have a look and proceed until you have understanding on Object Oriented
Concepts.

#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str1 = "Hello";
string str2 = "World";
string str3;
int len ;

// copy str1 into str3str3 =


str1;
cout << "str3 : " << str3 << endl;

// concatenates str1 and str2str3 =


str1 + str2;
cout << "str1 + str2 : " << str3 << endl;

// total lenghth of str3 after concatenationlen =


str3.size();
cout << "str3.size() : " << len << endl;

return 0;
}

When the above code is compiled and executed, it produces result something as follows:

str3 : Hello
str1 + str2 : HelloWorld str3.size() : 10

cin and strings


The extraction operator can be used on cin to get strings of characters in the same way as with fundamental data
types:

string mystring;
cin >> mystring;
However, cin extraction always considers spaces (whitespaces, tabs, new-line...) as terminating the value being
extracted, and thus extracting a string means to always extract a single word, not a phrase or an entire sentence.

To get an entire line from cin, there exists a function, called getline, that takes the stream (cin) as first argument,
and the string variable as second. For example:

// cin with strings #include <iostream> What's your name? Homer Simpson Hello Homer
#include <string> using namespace std; Simpson.
What is your favorite team? The Isotopes I like
int main () The Isotopes too!
{
string mystr;
cout << "What's your name? "; getline (cin,
mystr);
cout << "Hello " << mystr << ".\n"; cout <<
"What is your favorite team? "; getline (cin,
mystr);
cout << "I like " << mystr << " too!\n"; return 0;
}

Notice how in both calls to getline, we used the same string identifier (mystr). What the program does in the
second call is simply replace the previous content with the new one that is introduced.
C-String manipulation

C++ provides following two types of string representations:

 The C-style character string.


 The string class type introduced with Standard C++.

The C-Style Character String:

The C-style character string originated within the C language and continues to be supported
within C++. This string is actually a one-dimensional array of characters which is terminated by
a null character '\0'. Thus a null-terminated string contains the characters that comprise the string
followed by a null.

The following declaration and initialization create a string consisting of the word "Hello". To
hold the null character at the end of the array, the size of the character array containing the string
is one more than the number of characters in the word "Hello."

char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};


If you follow the rule of array initialization, then you can write the above statement as follows:

char greeting[] = "Hello";

Following is the memory presentation of above defined string in C/C++:

Actually, you do not place the null character at the end of a string constant. The C++ compiler
automatically places the '\0' at the end of the string when it initializes the array. Let us try to print
above-mentioned string:

#include <iostream>

using namespace std;

int main ()
{
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};

cout << "Greeting message: ";


cout << greeting << endl;

return 0;
}

When the above code is compiled and executed, it produces result something as follows:

Greeting message:

Hello
C++ supports a wide range of functions that manipulate null-terminated strings:

Function & Purpose


strcpy(s1, s2);
1
Copies string s2 into string s1.
strcat(s1, s2);
2
Concatenates string s2 onto the end of string s1.
strlen(s1);
3
Returns the length of string s1.
strcmp(s1, s2);
4
Returns 0 if s1 and s2 are the same; less than 0 if s1<s2; greater than 0 if s1>s2.
strchr(s1, ch);
5
Returns a pointer to the first occurrence of character ch in string s1.
strstr(s1, s2);
6
Returns a pointer to the first occurrence of string s2 in string s1.

Following example makes use of few of the above-mentioned functions:

#include <iostream>
#include <cstring>
using namespace std;
int main ()
{
char str1[10] =
"Hello"; char str2[10]
= "World"; char
str3[10];
int len ;

// copy str1 into str3


strcpy( str3, str1);
cout << "strcpy( str3,
str1) : " << str3 <<
endl;

// concatenates str1 and


str2 strcat( str1, str2);
cout << "strcat( str1,
str2): " << str1 <<
endl;

// total lenghth of str1


after concatenation len
= strlen(str1);
cout << "strlen(str1) :
" << len << endl;

return 0;
}

When the above code is compiled and executed, it produces result something as follows:

strcpy( str3, str1)


:Hello
strcat( str1, str2):
HelloWorld
strlen(str1) : 10
C- string manipulation

A string can be created by using a pointer or an array of characters.

Using pointer

char * string_name;
where: string_name is a pointer.
Example: char *lastname;
char * firstname;

Using array
char string_name[size];
where: size is the number of characters including the null character \0 stored in the array..
Example: char lastname[30];
char firstname[20];

STRING DECLARATION AND INITIALIZATION

A string can be declared and initialized by using a pointer or an array of characters. Using

pointer char * string_name = "string_value";


where: string_name is a pointer.
Example: char *lastname = "Nguyen";
char * firstname = "Phuong";

Using array char string_name[size] = "string-value";


where: size is the number of characters including the null character \0 stored in the array..
Example: char lastname[30] = "Nguyen";
char firstname[20] = "Phuong";

STRING INPUT AND OUTPUT

Table below lists the commonly available library functions for string input and output

C++ Routine Description


cout String output to the screen
String input from the keyboard, but cin does not input a space character. It
cin stops input a string when it reads a space character.
cin.getline(str, String input from the keyboard. cin.getline( ) read a spacecharacter.
length,char)
str - a string of character pointer or a character array.
length - an integer constant or a variable indicating the maximumnumber
of input characters including the null character.
char - an optional character constant or variable specifying the
terminating character. If this optional third argument is omitted,the
default terminating character is the newline (\n) character.
Pressing the enter key generates a newline character. A statement such as
cin.getline(message,80,'x') will stop accepting characters whenever the x
key is pressed.

Input single character from the keyboard.chr -


chr = cin.get( )
a character constant variable

Example Output
#include<iostream>
using namespace std;
int main( ) Enter a string for message1:
{char message1[80]; Good morning
char *message2; Enter a string for message2:
cout <<"Enter a string for message1: \n"; have a nice day
cin.getline(message1,80); Good morning and have a nice
cout << "Enter a string for message2: \n"; day
cin.getline(message2,80);
cout <<message1<< " and " <<message2;
}

STRING LIBRARY FUNCTIONS

Extensive collections of string-handling functions are included with all C++ compilers. The
common of these are listed below. To call these functions, you needto include the header file
<string.h> in your program.

String copy
strcpy(string1,string2) - Copies string2 to string1. String1 needs to have enoughspace
to store string2. The
strcpy will overwrite string1.

Example: char message1[80] ="Good morning", message2[80]="Hello World";cout


<<message1<<endl;
strcpy(message1,message2);
cout << message1;
Output
Good morning
Hello World

String concatenation
strcat(string1,string2) - concatenates string2 to string1. String1 needs tohave
enough space to append
string2.

Example: char message1[80] ="Good morning", message2[80]=" and have a niceday";


cout <<message1<<endl;
strcat(message1,message2);
cout << message1<<endl; cout
<< message2;
Output
Good morning
Good morning and have a nice dayand
have a nice day

String comparison
strcmp(string1, string2) - Compares string1 to string2. Returns a negative integer if
string1<string2, 0 if string1
is equal to string2, and a positive integer if string1 > string2.

Example: char message1[80] = "It's a cow";


char *mesaage2 = "It's a Cow";
if ( strcmp(string1,string2) )
cout << "string 1 is greater than string2";else
cout << "string1 is smaller than string2";
Ouput
string 1 is greater than string2

Note: When strcmp compare the character c in string1 with the character C in string2.The
character c is greater than the character C because the asscii value of character c is 99 and the
asscii value of character C is only 67. See the Appendix B ASCII character set in the back of
your text book.

String length
strlen(string1) - Return the length of the string, excluding the null character
Example: char message[80] = "Hello world";int
i;
i = strlen(message);
cout << i << " characters";
Output
11 characters

Note: a space is counted as one character.

CHARACTER STRING FUNCTIONS

C++ provides several functions that allow you to test and manipulate character data. The
function prototypes are found in the header file name <ctype.h>. Remember to add the line
#include <ctype.h> in program that use these functions. The table below lists and describes the
character functions. Each function expects one integer argument - the ASCII value of the
character to be tested. Each function returns a non-zero value (true) if the condition tested is true
and 0 (false) if the condition tested is false.

C++ Functions Description


Returns a nonzero number if the character is a letter ('A' - 'Z', 'a' -'z');
isalpha(character) otherwise it returns zero.
Returns a nonzero number if the character is a letter ('A' - 'Z', 'a' -'z', or '0'
isalnum(character) - '9'; otherwise it returns zero.
Returns a nonzero number if the character is digit (0 through 9);otherwise
isdigit(character) it returns a zero.
Returns a nonzero number if the character is a whitespace (tab,space,
isspace(character) newline); otherwise it returns a zero.
Returns a nonzero number if the character is uppercase;
isupper(character) otherwise it returns a zero.
Returns a nonzero number if the character is lowercase;
islower(character) otherwise it returns a zero.
Return the uppercase equivalent if the character is lowercase;
toupper(character) otherwise it returns the character unchanged.
Return the lowercase equivalent if the character is uppercase;
tolower(character)
otherwise it returns the character unchanged.
C++ Functions Description
Return the uppercase equivalent if the character is lowercase;
toupper(character) otherwise it returns the character unchanged.
Return the lowercase equivalent if the character is uppercase;
tolower(character) otherwise it returns the character unchanged.
Converts an ASCII string to an integer (include #<stdlib.h> inyour
atoi(string)
program)
Converts an ASCII string to an float (include #<stdlib.h> in yourprogram)
atof(string)

The example below will convert each lowercase character of a string to uppercasecharacter and
vice versa.

Example
#include<iostream>
#include<string>
#include<cctype>
using namespace std;
int main( )
{ char name[20];
cout<<"Enter your name:\n ";
cin.getline(name,20);
for( int i = 0; i < strlen(name) ; i++)
{ if (islower(name[i]) )
//convert to uppercase
name[i] = toupper(name[i]);
else
//convert to lowercase
name[i] = tolower(name[i]);
}
//Display the result
cout << "The conversion is:\n";
cout << name << endl;
}
Output
Enter your name:
Phuong D. Nguyen
The conversion is:
pHUONG d. nGUYEN

You can rewrite the example above using the pointer.


Example
#include<iostream>
#include<string>
#include<cctype>
using namespace std;
int main()
{ char *name;
cout<<"Enter your name:\n ";
cin.getline(name,20);
for( int i = 0; i < strlen(name) ; i++)
{ if (islower(*(name + i) ) )
//convert to uppercase
*( name + i) = toupper(*(name + i));
else
//convert to lowercase
*( name + i) = tolower(*(name + i));
}
//Display the result
cout << "The conversion is:\n";
cout << name << endl;
}

Output
Enter your name:
Phuong D. Nguyen
The conversion is:
pHUONG d. nGUYEN

Write a function that returns the number of digits in a given null-terminated string.

#include<iostream>
#include<cctype>
using namespace std;
int numAlphas(const char* s)
{
int count = 0;
for (int i = 0; s[i] != '\0'; i++)
{
if (isdigit(s[i]))
{
count++;
}
}
return count;
}

int main()
{
char str[] = "a12bc3d";
cout << numAlphas(str);

C Strings and Pointers

// Create your own strlen function


#include <iostream>
using namespace std;
int myStrLen(char str[]);

int main()
{
char s[15] = "Hello World";
cout << myStrLen(s);
return 0;
}
//
int myStrLen(char str[])
{
int i = 0;
while (str[i] != '\0')
i++;
return i;
}

Or

int myStrLen(char *str)


{
char *first = str;
while (*str != '\0')
str++; return
str - first;
}

Or

int myStrLen(char *str)


{
char *first = str;
while (*str)
str++; return
str - first;

}
// create your own strcpy function
#include <iostream>
using namespace std;
void myStrcpy(char str2[], char str1[]);int
main()
{
char s1[15] = "Hello World";
char s2[30];
myStrcpy(s2, s1);
cout << s2; return
0;
}
//
void myStrcpy(char *to, char * from)
{
while (*to = *from)
{
to++;
from++
;
}

Or

void myStrcpy(char *to, char * from)


{
while (*to++ = *from++);

}
Chapter:7 Function

 Basics,call by value
 call by reference & return by
reference
 Inline function
 Overloading Functions
 Recursive Functions
FUNCTION IN C++:
The main( )Functon ;
ANSI does not specify any return type for the main ( ) function which is the starting
point for the execution of a program .The definition of main( ) is :-
main()
{
//main program statements
}
This is property valid because the main () in ANSI C does not return any value. In C++,
the main () returns a value of type int to the operating system. The functions that have a return
value should use the return statement for terminating.
The main () function in C++ is therefore defined as follows.
int main( )
{
--------------
--------------
return(0)
}
Since the return type of functions is int by default, the key word int in the main( ) header
is optional.
INLINE FUNCTION:
To eliminate the cost of calls to small functions C++ proposes a new feature called
inline function. An inline function is a function that is expanded inline when it is invoked. That
is the compiler replaces the function call with the corresponding function code.
The inline functions are defined as follows:-
inline function-header
{
function body;
}
Example: inline double cube (double a)
{
return(a*a*a);
}
The above inline function can be invoked by statements like
c=cube(3.0);
d=cube(2.5+1.5);
remember that the inline keyword merely sends a request, not a command to the compliler. The
compiler may ignore this request if the function definition is too long or too complicated and
compile the function as a normal function.
Some of the situations where inline expansion may not work are:
1. For functions returning values if a loop, a switch or a go to exists.
2. for function s not returning values, if a return statement exists.
3. if functions contain static variables.
4. if inline functions are recursive,.
Example:
#include<iostream.h>
#include<stdio.h>
inline float mul(float x, float y)
{
return(x*y);
}
inline double div(double p.double q)
{
return(p/q);
}
main( )
{
float a=12.345;
float b=9.82;
cout<<mul(a,b)<<endl;
cout<<div (a,b)<<endl;
}
output:-
121.227898
1.257128

DEFAULT ARGUMENT: -
C++ allows us to call a function with out specifying all its arguments.In such cases, the
function assigns a default value to the parameter which does not have a matching aguments in
the function call. Default values are specified when the function is declared .The compiler looks
at the prototype to see how many arguments a function uses and alerts the program for possible
default values.
Example: float amount (float principle, int period, float rate=0.15);
The default value is specified in a manner syntactically similar to a variable
initialization. The above prototype declares a default value of 0.15 to the argument rate. A
subsequent function call like value=amount (5000,7); //one argument missing passes the value
of 5000 to principle and 7 to period and then lets the function, use default value of 0.15 for
rate.
The call: - value=amount (5000,5,0.12); //no missing argument passes an explicite
value of 0.12 rate. One important point to note is that only the trailing arguments can have
default values. That is, we must add default from right to left. We cannot provide a default to
a particular argument in the middle of an argument list.
Example: -
int mul(int i, int j=5,int k=10);//illegal
int mul(int i=0,int j,int k=10);//illegal
int mul(int i=5,int j);//illegal
int mul(int i=2,int j=5,int k=10);//illegal
Default arguments are useful in situation whose some arguments always have the some
value.
For example, bank interest may retain the same for all customers for a particular period of
deposit.
Example:
#include<iostream.h>
#include<stdio.h>
mainQ
{
float amount;
float value(float p,int n,float r=0.15);
void printline(char ch=‟*‟,int len=40);
printline( );
amount=value(5000.00,5);
cout<<”\n final value=”<<amount<<endl;
printline(„=‟);
//function definitions
float value (float p,int n, float r)
{
float si;
si=(p*n*r)/100;
return(si);
}
void printline (char ch,int len)
{
for(inti=l;i<=len;i++)
cout<<ch<<endl;
}
output:-
****************
final value=10056.71613
===============
Advantage of providing the default arguments are:
1. We can use default arguments to add new parameters to the existing functions.
2. Default argument s can be used to combine similar functions into one.

CONST ARGUMENT: -
In C++, an argument to a function can be declared as unit as const as shown
below.

int strlen(const char *p); int


length(const string &s);
The qualifier const tells the compiler that the function should not modify the argument.
the compiler will generate an error when this condition is violated. This type of declaration is
significant only when we pass arguments by reference or pointers.
FUNCTION OVERLOADING:
Overloading refers to the use of the same thing for different purposes. C++ also permits
overloading functions. This means that we can use the same function name to creates functions
that perform a variety of different tasks. This is known as function polymorphism in oops.
Using the concepts of function overloading, a family of functions with one function
name but with different argument lists in the functions call. The correct function to be invoked
is determined by checking the number and type of the arguments but not on the function type.
For example an overloaded add() function handles different types of data as shown below.
//Declaration
int add(int a, int b); //prototype 1
int add (int a, int b, int c); //prototype 2
double add(double x, double y); //prototype 3
double add(double p , double q); //prototype 4
//function call
cout<<add(5,10); //uses prototype 1
cout<<add(15,10.0); //uses prototype 4
cout<<add(12.5,7.5); //uses prototype 3
cout<<add(5,10,15); //uses prototype 2

cout<<add (0.75,5); //uses prototype 5


A function call first matches the prototype having the same no and type of arguments
and then calls the appropriate function for execution.
The function selection invokes the following steps: -
a) The compiler first tries to find an exact match in which the types of actual
arguments are the same and use that function.
b) If an exact match is not found the compiler uses the integral promotions to the actual
arguments such as:
char to int
float to double to find a match
c)When either of them tails ,the compiler tries to use the built in conversions to the actual
arguments and them uses the function whose match is unique . If the conversion is possible to
have multiple matches, then the compiler will give error message.
Example:
long square (long n);
double square(double x);
A function call such as :- square(lO) Will cause an error because int argument can be
converted to either long or double .There by creating an ambiguous situation as to which
version of square( )should be used.
PROGRAM
#include<iostream.h>
int volume(double,int);
double volume( double , int );
double volume(longint ,int ,int);
main( )
{
cout<<volume(10)<<endl;
cout<<volume(10)<<endl; cout<<volume(10)<<endl;
}
int volume( ini s)
{
return (s*s*s); //cube
}
double volume( double r, int h)
{
return(3.1416*r*r*h); //cylinder
}
long volume (longint 1, int b, int h)
{
return(1*b*h); //cylinder
}
output:- 1000
157.2595
112500
Recursion in C++
What Is Recursion?
Recursion is the process of calling the function by itself as its subroutine to solve the
complex program. Recursion uses the method of dividing the program into sub-tasks and
calling it repeatedly instead of the iterative method which takes lots of effort and time to
solve the same problem. Therefore, the function which calls itself is called the recursive
function, and the process of calling a function by itself is called recursion. The most
important thing about the recursion is it should have the base case to terminate the recursion.
As the recursive function calls itself continuously, it is always possible that the program goes
into the infinite loop. So if we create the terminate base case using the if..else statement, the
program will check the base case condition every time and prevent going into the infinite
loop.
How Does Recursion Work?
The function of the recursion approach is to solve the problem effectively in
comparison to another problem-solving approach. The recursion process divides the problem
into the subtask as a function and continuously calls the same function again to get one step
closer to the final solution. This process continues until we find the final solution to the
problem. Each time the part of the solution is found, it is stored in the form of stack data
structure in the memory and at last, popped out to get the final solution. As we approach the
final solution, there is a base condition that should be checked to get out of the recursion
process. This base condition is checked using the conditional statement and hence avoids the
recursion process to get into the infinite loop. If for any reason the base case fails to work, the
program will fall into an infinite loop and we will never reach the solution of the program.
Below is the working of recursion in C++.

void recursion()
{
... .. ...
recursion();
... .. ...
}

int main()
{
... .. ...
recursion();
... .. ...
}

The figure below shows how recursion works by calling the recursive function again and
again.
There are two types of recursive function i.e. direct recursion and indirect recursion.
Direct recursion is when the function calls itself just like we saw in the above program.
Indirect recursion is when the function calls another function and then that function calls the
calling function.
Advantages of C++ Recursion

 Less number code lines are used in the recursion program and hence the code looks
shorter and cleaner.
 Recursion is easy to approach to solve the problems involving data structure and
algorithms like graph and tree
 Recursion helps to reduce the time complexity
 It helps to reduce unnecessary calling of the function
 It helps to solve the stack evolutions and prefix, infix, postfix evaluation
 Recursion is the best method to define objects that have repeated structural forms

Disadvantages of C++ Recursion

 It consumes a lot of stack space


 It takes more time to process the program
 If an error is accrued in the program, it is difficult to debug the error in comparison to
the iterative program.

The recursion approach is the most important method to solve any program and therefore,
there are many popular problem statements which are asked in technical interviews to test
your level of understanding of the concept of recursion.
Top 5 Recursion C++ Examples
Below, we will study some of that recursive programs as an example along with their C++
code.

1) Fibonacci Series Using Recursion in C++


Fibonacci number series is the sequence of numbers such that each number is the sum of the
two preceding ones starting from zero(0) and one(1).

C++ program
#include <iostream>
using namespace std;
int fibonnaci(int x) {
if((x==1)||(x==0)) {
return(x);
}else {
return(fibonnaci(x-1)+fibonnaci(x-2));
}
}
int main() {
int x , i=0;
cout << "Enter the number of terms of series : ";
cin >> x;
cout << "\nFibonnaci Series : ";
while(i < x) {
cout << " " << fibonnaci(i);
i++;
}
return 0;
}

Output
Enter the number of terms of series : 15

Fibonnaci Series : 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

Here in the above program, the "fibonacci" function is the recursive function which calls
itself and finds the Fibonacci series.

The time complexity by the recursive Fibonacci program is O(n^2) or exponential.


2) Factorial Program Using Recursion In C++
Factorial is the product of an integer and all other integers below it. For example, the
factorial of 5 (5!) is equal to 5x4x3x2x1 i.e. 120.

C++ program
#include <iostream>
using namespace std;

int fact(int n);

int main()
{
int n;

cout << "Enter a positive integer: ";


cin >> n;

cout << "Factorial of " << n << " = " << fact(n);

return 0;
}

int fact(int n)
{
if(n > 1)
return n * fact(n - 1);
else
return 1;
}

Output
Enter an positive integer: 6

Factorial of 6 = 720

Here the recursive function "fact" will take a number as a parameter for which we
want to find the factorial. And then recursively call the function until the base condition
becomes true which is when the number as a parameter becomes 1.

The time complexity for the recursive factorial program is O(n) because only one loop
is executed at a time while finding the factorial of the number using the recursive function.
Also, there is no extra space required during recursive calls and therefore, the space
complexity is also O(n).
3) Program To Calculate Number Power Using Recursion In C++
In this program, we will calculate the power of the number using the recursion
approach where the base and exponent is taken as input by the user.

C++ Program
#include <iostream>
using namespace std;

int calculate(int, int);

int main()
{
int base, power, result;

cout << "Enter base number: ";


cin >> base;

cout << "Enter power number(positive integer): ";


cin >> power;

result = calculate(base, power);


cout << base << "^" << power << " = " << result;

return 0;
}

int calculate(int base, int power)


{
if (power != 0)
return (base*calculate(base, power-1));
else
return 1;
}

Output
Enter base number: 3

Enter power number(positive integer): 4

3^4 = 81

Here the recursice function "calculate" calls itself again and again with the base
condition to check the power until 0 because the exponent is always the positive integer.

The running time complexity for the program to find the power of the number using
recursion is O(logn) because every time the recursive function is called, the parameter of the
next call is increased by exponential times. Therefore, the time complexity is the function of
the log.
4) Reverse A Number Using Recursion In C++
In this program, we will take input from the user as an integer number and reverse it
using the recursive function.

C++ program
#include <iostream.h>
using namespace std;

int reverseNumber(int n) {

static temp,sum;

if(n>0){

temp = n%10;
sum = sum*10 + temp;

reverseNumber(n/10);

} else {

return sum;
}

int main() {

int n,reverse;

cout<<"Enter number";
cin >> n;

reverse = reverseNumber(n);

cout << "Reverse of number is" << reverse;

return 0;
}

Output
Enter number : 3456
Reverse of number is : 6543

In this program, we will recursively call the "reverseNumber" function with the parameter
that the user entered.
The running time complexity of the program is O(log(n)) because every time the function is
called recursively, it takes 1/10 of the number as a parameter for the next call. Therefore, the
time complexity for reversing the number using the recursive function is O(log(n)).

5) Checking Whether The Number Is Prime Or Not Using Recursion In C++


A prime number is a number that is divisible only by itself and 1. In this program, we
will check whether the given number is a prime number or not.

C++ program
#include <bits/stdc++.h>
using namespace std;

bool isprime(int n, int i = 2)


{
if (n <= 2)
return (n == 2) ? true : false;
if (n % i == 0)
return false;
if (i * i > n)
return true;

return isprime(n, i + 1);


}

int main()
{
int n = 18;
if (isprime(n))
cout << "Yes, Number is Prime Number";
else
cout << "No, Number is not Prime Number";

return 0;
}

Output
No, Number is not Prime Number

Here, we create the recursive function "isprime" and all it recursively and then check the
prime number condition using conditional statements.

The running time complexity of the program to check whether the number is prime or not is
O(sqrt(n)) because when we recursively call the function isPrime we check whether it is less
than the square root of the given number.
Chapter:8 Pointers
 Pointers
 Dynamic Memory Allocation

1
1. Pointer Variables
A computer memory location has an address and holds a content. The address is a numerical
number (often expressed in hexadecimal), which is hard for programmers to use directly.
Typically, each address location holds 8-bit (i.e., 1-byte) of data. It is entirely up to the
programmer to interpret the meaning of the data, such as integer, real number, characters or
strings.
To ease the burden of programming using numerical address and programmer-interpreted data,
early programming languages (such as C) introduce the concept of variables. A variable is a
named location that can store a value of a particular type. Instead of numerical addresses, names
(or identifiers) are attached to certain addresses. Also, types (such as int, double, char) are
associated with the contentsfor ease of interpretation of data.
Each address location typically hold 8-bit (i.e., 1-byte) of data. A 4-byte int value occupies 4
memory locations. A 32-bit system typically uses 32-bit addresses. To store a 32-bit address, 4
memory locations are required.
The following diagram illustrate the relationship between computers' memory address and
content; and variable's name, type and value used by the programmers.

2
2. Pointer Variables (or Pointers)
A pointer variable (or pointer in short) is basically the same as the other variables, which can
store a piece of data. Unlike normal variable which stores a value (such as an int, a double, a
char), a pointerstores a memory address.
3. Declaring Pointers
Pointers must be declared before they can be used, just like a normal variable. The syntax of
declaring a pointer is to place a * in front of the name. A pointer is associated with a
type (suchas int and double) too.
type *ptr; // Declare a pointer variable called ptr as a pointer of type
// or
type* ptr;
// or
type * ptr; // I shall adopt this convention

For example,
int * iPtr; // Declare a pointer variable called iPtr pointing to an int (an int
pointer)
// It contains an address. That address holds an int value.
double * dPtr; // Declare a double pointer
Take note that you need to place a * in front of each pointer variable, in other words, * applies only
to the name that followed. The * in the declaration statement is not an operator, but indicates that
the name followed is a pointer variable. For example,
int *p1, *p2, i; // p1 and p2 are int pointers. i is an int
int* p1, p2, i; // p1 is a int pointer, p2 and i are int
int * p1, * p2, i; // p1 and p2 are int pointers, i is an int
Naming Convention of Pointers: Include a "p" or "ptr" as prefix or suffix,
e.g., iPtr, numberPtr, pNumber, pStudent.
4. Initializing Pointers via the Address-Of Operator (&)
When you declare a pointer variable, its content is not initialized. In other words, it contains an
address of "somewhere", which is of course not a valid location. This is dangerous! You need to
initialize a pointer by assigning it a valid address. This is normally done via the address-of
operator (&).
The address-of operator (&) operates on a variable, and returns the address of the variable. For
example,if numberis an int variable, &number returns the address of the variable number.
You can use the address-of operator to get the address of a variable, and assign the address to a
pointer variable. For example,

int number = 88; // An int variable with a value


int * pNumber; // Declare a pointer variable called pNumber pointing to an int
(or int pointer)
pNumber = &number; // Assign the address of the variable number to pointer pNumber

int * pAnother = &number; // Declare another int pointer and init to address of the
variable number

3
As illustrated, the int variable number, starting at address 0x22ccec, contains an int value 88. The
expression &number returns the address of the variable number, which is 0x22ccec. This address
is thenassigned to the pointer variable pNumber, as its initial value.
The address-of operator (&) can only be used on the RHS.
5. Indirection or Dereferencing Operator (*)
The indirection operator (or dereferencing operator) (*) operates on a pointer, and returns the
value stored in the address kept in the pointer variable. For example, if
pNumber isan int pointer, *pNumber returns the int value "pointed to" by pNumber.
For example,
int number = 88;
int * pNumber = &number; // Declare and assign the address of variable number to
pointer pNumber (0x22ccec)
cout << pNumber<< endl; // Print the content of the pointer variable, which contain
an address (0x22ccec)
cout << *pNumber << endl; // Print the value "pointed to" by the pointer, which is an
int (88)
*pNumber = 99; // Assign a value to where the pointer is pointed to, NOT to
the pointer variable
cout << *pNumber << endl; // Print the new value "pointed to" by the pointer (99)
cout << number << endl; // The value of variable number changes as well (99)
Take note that pNumber stores a memory address location, whereas *pNumber refers to the value
stored in the address kept in the pointer variable, or the value pointed to by the pointer.
As illustrated, a variable (such as number) directly references a value, whereas a
pointer indirectly references a value through the memory address it stores. Referencing a value
indirectly via a pointer is called indirection or dereferencing.
The indirection operator (*) can be used in both the RHS (temp = *pNumber) and the LHS (*pNumber
= 99) of an assignment statement.
Take note that the symbol * has different meaning in a declaration statement and in an
expression. When it is used in a declaration (e.g., int * pNumber), it denotes that the name
followed is a pointer variable. Whereas when it is used in a expression (e.g., *pNumber = 99;
temp << *pNumber;), it refersto the value pointed to by the pointer variable.
5.1 Pointer has a Type Too
4
A pointer is associated with a type (of the value it points to), which is specified during
declaration. Apointer can only hold an address of the declared type; it cannot hold an address of a
int i = 88;
double d = 55.66;
int * iPtr = &i; // int pointer pointing to an int value
double * dPtr = &d; // double pointer pointing to a double value

iPtr = &d; // ERROR, cannot hold address of different type


dPtr = &i; // ERROR
iPtr = i; // ERROR, pointer holds address of an int, NOT int value

int j = 99;
iPtr = &j; // You can change the address stored in a pointer
different type.
Example

1/* Test pointer declaration and initialization (TestPointerInit.cpp) */


2#include <iostream>
3using namespace std;
4
5int main() {
6 int number = 88; // Declare an int variable and assign an initial value
7 int * pNumber; // Declare a pointer variable pointing to an int (or int pointer)
8 pNumber = &number; // assign the address of the variable number to pointer pNumber
9
10 cout << pNumber << endl; // Print content of pNumber (0x22ccf0)
11 cout << &number << endl; // Print address of number (0x22ccf0)
12 cout << *pNumber << endl; // Print value pointed to by pNumber (88)
13 cout << number << endl; // Print value of number (88)
14
15 *pNumber = 99; // Re-assign value pointed to by pNumber
16 cout << pNumber << endl; // Print content of pNumber (0x22ccf0)
17 cout << &number << endl; // Print address of number (0x22ccf0)
18 cout << *pNumber << endl; // Print value pointed to by pNumber (99)
19 cout << number << endl; // Print value of number (99)
20 // The value of number changes via pointer
21
22 cout << &pNumber << endl; // Print the address of pointer variable pNumber (0x22ccec)
23}

Notes: The address values that you get are unlikely to be the same as mine. The OS loads the
programin available free memory locations, instead of fixed memory locations.
6. Uninitialized Pointers

The following code fragment has a serious logical error!


5
int * iPtr;
*iPtr = 55;
cout << *iPtr << endl;

The pointer iPtr was declared without initialization, i.e., it is pointing to "somewhere" which is of
course an invalid memory location. The *iPtr = 55 corrupts the value of "somewhere"! You need
to initialize a pointer by assigning it a valid address. Most of the compilers does not signal an
error or a warning for uninitialized pointer?!
7. Null Pointers
You can initialize a pointer to 0 or NULL, i.e., it points to nothing. It is called a null pointer.
Dereferencinga null pointer (*p) causes an STATUS_ACCESS_VIOLATION exception.
int * iPtr = 0; // Declare an int pointer, and initialize the pointer to point
to nothing
cout << *iPtr << endl; // ERROR! STATUS_ACCESS_VIOLATION exception

int * p = NULL; // Also declare a NULL pointer points to nothing

Initialize a pointer to null during declaration is a good software engineering


practice.C++11 introduces a new keyword called nullptr to represent null pointer.

8. Reference Variables
C++ added the so-called reference variables (or references in short). A reference is an
alias, or an alternate name to an existing variable. For example, suppose you make peter a
reference (alias)to paul, you can refer to the person as either peteror paul.
The main use of references is acting as function formal parameters to support pass-by-reference.
In an reference variable is passed into a function, the function works on the original copy
(instead of a clone copy in pass-by-value). Changes inside the function are reflected outside the
function.
A reference is similar to a pointer. In many cases, a reference can be used as an alternative to
pointer,in particular, for the function parameter.
9. References (or Aliases) (&)
Recall that C/C++ use & to denote the address-of operator in an expression. C++ assigns an
additionalmeaning to &in declaration to declare a reference variable.
The meaning of symbol & is different in an expression and in a declaration. When it is used in an
expression, & denotes the address-of operator, which returns the address of a variable, e.g., if
number is an int variable, &number returns the address of the variable number (this has been
described in the above section).
Howeve, when & is used in a declaration (including function formal parameters), it is part of the
type identifier and is used to declare a reference variable (or reference or alias or alternate
name). It is usedto provide another name, or another reference, or alias to an existing variable.
The syntax is as follow:
6
type &newName = existingName;
// or
type& newName = existingName;
// or
type & newName = existingName; // I shall adopt this convention
It shall be read as "newName is a reference to exisitngName", or "newNew is an alias of
existingName".You can now refer to the variable as newName or existingName.
For example,

1/* Test reference declaration and initialization (TestReferenceDeclaration.cpp) */2#include <iostream>


3using namespace std;4
5int main() {
6 int number = 88; // Declare an int variable called number
7 int & refNumber = number; // Declare a reference (alias) to the variable number
8 // Both refNumber and number refer to the same value
9
10 cout << number << endl; // Print value of variable number (88)cout <<
11 refNumber << endl; // Print value of reference (88)
12
13 refNumber = 99; // Re-assign a new value to refNumbercout
14 << refNumber << endl;
15 cout << number << endl; // Value of number also changes (99)
16
number = 55; // Re-assign a new value to numbercout
17
<< number << endl;
18
cout << refNumber << endl; // Value of refNumber also changes (55)
19
20
}

10. How References Work?

A reference works as a pointer. A reference is declared as an alias of a variable. It stores the


address ofthe variable, as illustrated:

7
11. References vs. Pointers

Pointers and references are equivalent, except:


1. A reference is a name constant for an address. You need to initialize the reference
duringdeclaration.
int & iRef; // Error: 'iRef' declared as reference but not initialized
Once a reference is established to a variable, you cannot change the reference to reference
another variable.
2. To get the value pointed to by a pointer, you need to use the dereferencing operator *
(e.g., if pNumber is a int pointer, *pNumber returns the value pointed to by pNumber.
It is called dereferencing or indirection). To assign an address of a variable into a pointer,
you need to use the address-of operator & (e.g., pNumber =
&number). On the other hand, referencing and dereferencing are done on the references
implicitly. For example, if refNumber is a reference (alias) to another int variable,
refNumber returns the value of the variable. No explicit dereferencing operator * should be
used. Furthermore, to assign an address of a variable to a reference variable, no address-of
operator & is needed.
For example,

1/* References vs. Pointers (TestReferenceVsPointer.cpp) */


2#include <iostream>
3using namespace std;
4
5int main() {
6 int number1 = 88, number2 = 22;
7
8 // Create a pointer pointing to number1
9 int * pNumber1 = &number1; // Explicit referencing
10 *pNumber1 = 99; // Explicit dereferencing
11 cout << *pNumber1 << endl; // 99
12 cout << &number1 << endl; // 0x22ff18
13 cout << pNumber1 << endl; // 0x22ff18 (content of the pointer variable - same as abov
8
14 cout << &pNumber1 << endl; // 0x22ff10 (address of the pointer variable)
15 pNumber1 = &number2; // Pointer can be reassigned to store another address
16
17 // Create a reference (alias) to number1
18 int & refNumber1 = number1; // Implicit referencing (NOT &number1)
19 refNumber1 = 11; // Implicit dereferencing (NOT *refNumber1)
20 cout << refNumber1 << endl; // 11
21 cout << &number1 << endl; // 0x22ff18
22 cout << &refNumber1 << endl; // 0x22ff18
23 //refNumber1 = &number2; // Error! Reference cannot be re-assigned
24 // error: invalid conversion from 'int*' to 'int'
25 refNumber1 = number2; // refNumber1 is still an alias to number1.
26 // Assign value of number2 (22) to refNumber1 (and number1
27 number2++;
28 cout << refNumber1 << endl; // 22
29 cout << number1 << endl; // 22
30 cout << number2 << endl; // 23
31}

A reference variable provides a new name to an existing variable. It is dereferenced implicitly and
does not need the dereferencing operator * to retrieve the value referenced. On the other hand, a
pointer variable stores an address. You can change the address value stored in a pointer. To
retrieve the value pointed to by a pointer, you need to use the indirection operator *, which is
known as explicit dereferencing. Reference can be treated as a const pointer. It has to be
initialized during declaration,and its content cannot be changed.
Reference is closely related to pointer. In many cases, it can be used as an alternative to pointer.
A reference allows you to manipulate an object using pointer, but without the pointer syntax of
referencing and dereferencing.
The above example illustrates how reference works, but does not show its typical usage, which is
usedas the function formal parameter for pass-by-reference.
12. Pass-By-Reference into Functions with Reference Arguments vs. Pointer Arguments
Pass-by-Value

In C/C++, by default, arguments are passed into functions by value (except arrays which is
treated as pointers). That is, a clone copy of the argument is made and passed into the function.
Changes to the clone copy inside the function has no effect to the original argument in the caller.
In other words, thecalled function has no access to the variables in the caller. For example,
1/* Pass-by-value into function (TestPassByValue.cpp) */
2#include <iostream>
3using namespace std;
4
5int square(int);
6

9
7int main() {
8 int number = 8;
9 cout << "In main(): " << &number << endl; // 0x22ff1c
10 cout << number << endl; // 8
11 cout << square(number) << endl; // 64
12 cout << number << endl; // 8 - no change
13}
14
15int square(int n) { // non-const
16 cout << "In square(): " << &n << endl; // 0x22ff00
17 n *= n; // clone modified inside the function
18 return n;
19}

The output clearly shows that there are two different addresses.
Pass-by-Reference with Pointer Arguments
In many situations, we may wish to modify the original copy directly (especially in passing huge
object or array) to avoid the overhead of cloning. This can be done by passing a pointer of the
object into the function, known as pass-by-reference. For example,
1/* Pass-by-reference using pointer (TestPassByPointer.cpp) */
2#include <iostream>
3using namespace std;
4
5void square(int *);
6
7int main() {
8 int number = 8;
9 cout << "In main(): " << &number << endl; // 0x22ff1c
10 cout << number << endl; // 8
11 square(&number); // Explicit referencing to pass an address
12 cout << number << endl; // 64
13}
14
15void square(int * pNumber) { // Function takes an int pointer (non-const)
16 cout << "In square(): " << pNumber << endl; // 0x22ff1c
17 *pNumber *= *pNumber; // Explicit de-referencing to get the value pointed-to
18}

The called function operates on the same address, and can thus modify the variable in the caller.
Pass-by-Reference with Reference Arguments
Instead of passing pointers into function, you could also pass references into function, to avoid
theclumsy syntax of referencing and dereferencing. For example,

1/* Pass-by-reference using reference (TestPassByReference.cpp) */

10
2#include <iostream>
3using namespace std;
4
5void square(int &);
6
7int main() {
8 int number = 8;
9 cout << "In main(): " << &number << endl; // 0x22ff1c
10 cout << number << endl; // 8
11 square(number); // Implicit referencing (without '&')
12 cout << number << endl; // 64
13}
14
15void square(int & rNumber) { // Function takes an int reference (non-const)
16 cout << "In square(): " << &rNumber << endl; // 0x22ff1c
17 rNumber *= rNumber; // Implicit de-referencing (without '*')
18}

Again, the output shows that the called function operates on the same address, and can thus
modify the caller's variable.
Take note referencing (in the caller) and dereferencing (in the function) are done implicitly. The
only coding difference with pass-by-value is in the function's parameter declaration.
Recall that references are to be initialized during declaration. In the case of function formal
parameter,the references are initialized when the function is invoked, to the caller's arguments.
References are primarily used in passing reference in/out of functions to allow the called
function accesses variables in the caller directly.
"const" Function Reference/Pointer Parameters
A const function formal parameter cannot be modified inside the function. Use const whenever
possible as it protects you from inadvertently modifying the parameter and protects you against
manyprogramming errors.
A const function parameter can receive both const and non-const argument. On the other hand, a
non-const function reference/pointer parameter can only receive non-const argument. For
example,
/* Test Function const and non-const parameter (FuncationConstParameter.cpp)
*/ #include <iostream>
using namespace std;
int squareConst(const int);
int squareNonConst(int);
int squareConstRef(const int &);
int squareNonConstRef(int &);

int main() {
int number = 8;

11
const int constNumber = 9;
cout << squareConst(number) << endl;
cout << squareConst(constNumber) << endl;cout <<
squareNonConst(number) << endl;
cout << squareNonConst(constNumber) << endl;

cout << squareConstRef(number) << endl;


cout << squareConstRef(constNumber) << endl;cout
<< squareNonConstRef(number) << endl;
// cout << squareNonConstRef(constNumber) << endl;
// error: invalid initialization of reference of
// type 'int&' from expression of type 'const int'
}

int squareConst(const int number) {


// number *= number; // error: assignment of read-only parameterreturn
number * number;
}

int squareNonConst(int number) { // non-const parameternumber *=


number;
return number;
}

int squareConstRef(const int & number) { // const referencereturn


number * number;
}

int squareNonConstRef(int & number) { // non-const referencereturn


number * number;
}
13. Passing the Function's Return Value
Passing the Return-value as Reference
You can also pass the return-value as reference or pointer. For example,

/* Passing back return value using reference (TestPassByReferenceReturn.cpp) */


#include <iostream>
using namespace std;
int & squareRef(int &);
int * squarePtr(int *);
int main() {
int number1 = 8;

12
cout << "In main() &number1: " << &number1 << endl; // 0x22ff14int &
result = squareRef(number1);
cout << "In main() &result: " << &result << endl; // 0x22ff14cout << result
<< endl; // 64
cout << number1 << endl; // 64

int number2 = 9;
cout << "In main() &number2: " << &number2 << endl; // 0x22ff10int *
pResult = squarePtr(&number2);
cout << "In main() pResult: " << pResult << endl; // 0x22ff10cout <<
*pResult << endl; // 81
cout << number2 << endl; // 81
}

int & squareRef(int & rNumber) {


cout << "In squareRef(): " << &rNumber << endl; // 0x22ff14rNumber *=
rNumber;
return rNumber;
}

int * squarePtr(int * pNumber) {


cout << "In squarePtr(): " << pNumber << endl; // 0x22ff10
*pNumber *=
*pNumber;return
pNumber;
}
You should not pass Function's local variable as return value by reference

13
}

int & squareRef(int number) {


int localResult = number * number;
return localResult;
// warning: reference of local variable 'localResult' returned
}
This program has a serious logical error, as local variable of function is passed back as return
value by reference. Local variable has local scope within the function, and its value is destroyed
after the function exits. The GCC compiler is kind enough to issue a warning (but not error).
It is safe to return a reference that is passed into the function as an argument. See earlier
examples.Passing Dynamically Allocated Memory as Return Value by Reference
Instead, you need to dynamically allocate a variable for the return value, and return it by
reference.
1/* Test passing the result (TestPassResultNew.cpp) */
2#include <iostream>
3using namespace std;
4
5int * squarePtr(int);
6int & squareRef(int);
7
8int main() {
9 int number = 8;
10 cout << number << endl; // 8
11 cout << *squarePtr(number) << endl; // 64
12 cout << squareRef(number) << endl; // 64
13}
14
15int * squarePtr(int number) {
16 int * dynamicAllocatedResult = new int(number * number);
17 return dynamicAllocatedResult;
18}
19
20int & squareRef(int number) {
21 int * dynamicAllocatedResult = new int(number * number);
22 return *dynamicAllocatedResult;
23}

14. Summary

Pointers and references are highly complex and difficult to master. But they can greatly
improve theefficiency of the programs.

14
For novices, avoid using pointers in your program. Improper usage can lead to serious logical
bugs. However, you need to understand the syntaxes of pass-by-reference with pointers and
references, because they are used in many library functions.
 In pass-by-value, a clone is made and passed into the function. The caller's copy cannot
bemodified.
 In pass-by-reference, a pointer is passed into the function. The caller's copy could be
modifiedinside the function.
 In pass-by-reference with reference arguments, you use the variable name as the argument.
 In pass-by-reference with pointer arguments, you need to use &varName(an address) as
theargument.

15. Dynamic Memory Allocation

15.1 new and delete Operators


Instead of define an int variable (int number), and assign the address of the variable to
the int pointer (int *pNumber = &number), the storage can be dynamically allocated at runtime,
via a new operator. In C++, whenever you allocate a piece of memory dynamically via new, you
need to use deleteto remove the storage (i.e., to return the storage to the heap).
The new operation returns a pointer to the memory allocated. The delete operator takes a pointer
(pointing to the memory allocated via new) as its sole argument.
For example,
// Static allocation
int number = 88;
int * p1 = &number; // Assign a "valid" address into pointer

// Dynamic Allocation
int * p2; // Not initialize, points to somewhere which is invalid
cout << p2 << endl; // Print address before allocation
p2 = new int; // Dynamically allocate an int and assign its address to pointer
// The pointer gets a valid address with memory allocated
*p2 = 99;
cout << p2 << endl; // Print address after allocation
cout << *p2 << endl; // Print value point-to
delete p2; // Remove the dynamically allocated storage
Observe that newand delete operators work on pointer.
To initialize the allocated memory, you can use an initializer for fundamental types, or
invoke aconstructor for an object. For example,
// use an initializer to initialize a fundamental type (such as int, double)
int * p1 = new int(88);
double * p2 = new double(1.23);

// C++11 brace initialization syntax


int * p1 = new int {88};
double * p2 = new double {1.23};

15
// invoke a constructor to initialize an object (such as Date, Time)
Date * date1 = new Date(1999, 1, 1);
Time * time1 = new Time(12, 34, 56);
You can dynamically allocate storage for global pointers inside a function. Dynamically
allocatedstorage inside the function remains even after the function exits. For example,
1// Dynamically allocate global pointers (TestDynamicAllocation.cpp)
2#include <iostream>
3using namespace std;
4
5int * p1, * p2; // Global int pointers
6
7// This function allocates storage for the int*
8// which is available outside the function
9void allocate() {
10 p1 = new int; // Allocate memory, initial content unknown
11 *p1 = 88; // Assign value into location pointed to by pointer
12 p2 = new int(99); // Allocate and initialize
13}
14
15int main() {
16 allocate();
17 cout << *p1 << endl; // 88
18 cout << *p2 << endl; // 99
19 delete p1; // Deallocate
20 delete p2;
21 return 0;
22}

The main differences between static allocation and dynamic allocations are:
1. In static allocation, the compiler allocates and deallocates the storage automatically, and
handle memory management. Whereas in dynamic allocation, you, as the programmer,
handle the memory allocation and deallocation yourself (via new and delete operators).
You have full control on the pointer addresses and their contents, as well as memory
management.
2. Static allocated entities are manipulated through named variables. Dynamic allocated
entities are handled through pointers.
15.2 new[] and delete[] Operators
Dynamic array is allocated at runtime rather than compile-time, via the new[] operator. To remove
thestorage, you need to use the delete[] operator (instead of simply delete). For example,
1/* Test dynamic allocation of array (TestDynamicArray.cpp) */
2#include <iostream>
3#include <cstdlib>
4using namespace std;
16
5
6int main() {
7 const int SIZE = 5;
8 int * pArray;
9
10 pArray = new int[SIZE]; // Allocate array via new[] operator
11
12 // Assign random numbers between 0 and 99
13 for (int i = 0; i < SIZE; ++i) {
14 *(pArray + i) = rand() % 100;
15 }
16 // Print array
17 for (int i = 0; i < SIZE; ++i) {
18 cout << *(pArray + i) << " ";
19 }
20 cout << endl;
21
22 delete[] pArray; // Deallocate array via delete[] operator
23 return 0;
24}

C++03 does not allow your to initialize the dynamically-allocated array. C++11 does with the
braceinitialization, as follows:
// C++11
int * p = new int[5] {1, 2, 3, 4, 5};

16. Pointer, Array and Function


16.1 Array is Treated as Pointer
In C/C++, an array's name is a pointer, pointing to the first element (index 0) of the array. For
example, suppose that numbers is an int array, numbers is a also an int pointer, pointing at the first
element ofthe array. That is, numbers is the same as
&numbers[0].Consequently, *numbers is number[0]; *(numbers+i) is numbers[i].
For example,

/* Pointer and Array (TestPointerArray.cpp) */


#include <iostream>
using namespace std;
int main() {

const int SIZE = 5;


int numbers[SIZE] = {11, 22, 44, 21, 41}; // An int array

// The array name numbers is an int pointer, pointing at the


// first item of the array, i.e., numbers = &numbers[0]

17
cout << &numbers[0] << endl; // Print address of first element (0x22fef8) cout <<
numbers << endl; // Same as above (0x22fef8)
cout << *numbers << endl; // Same as numbers[0] (11) cout <<
*(numbers + 1) << endl; // Same as numbers[1] (22) cout <<
*(numbers + 4) << endl; // Same as numbers[4] (41)
}
16.2 Pointer Arithmetic
As seen from the previous section, if numbers is an int array, it is treated as an int pointer
pointing to the first element of the array. (numbers + 1) points to the next int, instead of having
the next sequential address. Take note that an int typically has 4 bytes. That is (numbers + 1)
increases the address by 4, or sizeof(int). For example,
int numbers[] = {11, 22, 33};
int * iPtr = numbers;
cout << iPtr << endl; // 0x22cd30
cout << iPtr + 1 << endl; // 0x22cd34 (increase by 4 - sizeof int)
cout << *iPtr << endl; // 11
cout << *(iPtr + 1) << endl; // 22
cout << *iPtr + 1 << endl; // 12

16.3 sizeof Array


The operation sizeof(arrayName)returns the total bytes of the array. You can derive the length
(size)of the array by dividing it with the size of an element (e.g. element 0). For example,
int numbers[100];
cout << sizeof(numbers) << endl; // Size of entire array in bytes (400)
cout << sizeof(numbers[0]) << endl; // Size of first element of the array in bytes
(4)
cout << "Array size is " << sizeof(numbers) / sizeof(numbers[0]) << endl; // (100)

16.4 Passing Array In/Out of a Function


An array is passed into a function as a pointer to the first element of the array. You can use array
notation (e.g., int[]) or pointer notation (e.g., int*) in the function declaration. The compiler
always treats it as pointer (e.g., int*). For example, the following declarations are equivalent:
int max(int numbers[], int size);
int max(int *numbers, int size);
int max(int number[50], int size);
They will be treated as int* by the compiler, as follow. The size of the array given in [] is ignored.
int max(int*, int);
Array is passed by reference into the function, because a pointer is passed instead of a clone copy. If
the array is modified inside the function, the modifications are applied to the caller's copy. You
could declare the array parameter as const to prevent the array from being modified inside the
function.
The size of the array is not part of the array parameter, and needs to be passed in
another int parameter. Compiler is not able to deduce the array size from the array pointer, and
doesnot perform array bound check.
18
Example: Using the usual array notation.
/* Passing array in/out function (TestArrayPassing.cpp) */
#include <iostream>
using namespace std;
// Function prototypes
int max(const int arr[], int size);
void replaceByMax(int arr[], int size);
void print(const int arr[], int size);

int main() {
const int SIZE = 4;
int numbers[SIZE] = {11, 22, 33, 22};
print(numbers, SIZE);
cout << max(numbers, SIZE) << endl;
replaceByMax(numbers, SIZE);
print(numbers, SIZE);

}
// Return the maximum value of the given array.
// The array is declared const, and cannot be modified inside the function.21int max(const int
arr[], int size) {
} int max = arr[0]
for (int i = 1; i < size; ++i) { if (max < arr[i]) max = arr[i];
}
return max;
// Replace all elements of the given array by its maximum value
// Array is passed by reference. Modify the caller's copy.
void replaceByMax(int arr[], int size) {
int maxValue = max(arr, size); for (int
i = 0; i < size; ++i) {
arr[i] = maxValue;
}
}

// Print the array's content


void print(const int arr[], int size) {
cout << "{";
for (int i = 0; i < size; ++i) {
cout << arr[i];
if (i < size - 1) cout << ",";44 }
19
cout << "}" << endl;
}
Take note that you can modify the contents of the caller's array inside the function, as array is
passed by reference. To prevent accidental modification, you could apply const qualifier to the
function's parameter. Recall that const inform the compiler that the value should not be changed.
For example, suppose that the function print() prints the contents of the given array and does not
modify the array, you could apply const to both the array name and its size, as they are not
expected to be changed inside the function.
void print(const int arr[], int size);
Compiler flags out an error "assignment of read-only location" if it detected a const value would be
changed.
Example: Using pointer notation.
1/* Passing array in/out function using pointer (TestArrayPassingPointer.cpp) */
2#include <iostream>
3using namespace std;
4
5// Function prototype
6int max(const int *arr, int size);
7
8int main() {
9 const int SIZE = 5;
10 int numbers[SIZE] = {10, 20, 90, 76, 22};
11 cout << max(numbers, SIZE) << endl;
12}
13
14// Return the maximum value of the given array
15int max(const int *arr, int size) {
16 int max = *arr;
17 for (int i = 1; i < size; ++i) {
18 if (max < *(arr+i)) max = *(arr+i);19
}
20 return max;
21}

16.5 Pass-by-Reference and sizeof


1/* Test sizeof array (TestSizeofArray.cpp) */
2#include <iostream>
3using namespace std;
4
5// Function prototypes
6void fun(const int *arr, int size);
7
8// Test Driver

20
9int main() {
10 const int SIZE = 5;
11 int a[SIZE] = {8, 4, 5, 3, 2};
12 cout << "sizeof in main() is " << sizeof(a) << endl;
13 cout << "address in main() is " << a << endl;
14 fun(a, SIZE);
15}
16
17// Function definitions
18void fun(const int *arr, int size) {
19 cout << "sizeof in function is " << sizeof(arr) << endl;
20 cout << "address in function is " << arr << endl;
21}

sizeof in main() is 20
address in main() is 0x22fefc
sizeof in function is 4
address in function is 0x22fefc

The address of arrays in main() and the function are the same, as expected, as array is passed by
reference.
In main(), the sizeof array is 20 (4 bytes per int, length of 5). Inside the function, the sizeof is 4,
which is the sizeof int pointer (4-byte address). This is why you need to pass the size into the
function.
16.6 Operating on a Range of an Array
1/* Function to compute the sum of a range of an array (SumArrayRange.cpp) */
2#include <iostream>
3using namespace std;
4
5// Function prototype
6int sum(const int *begin, const int *end);
7
8// Test Driver
9int main() {
10 int a[] = {8, 4, 5, 3, 2, 1, 4, 8};
11 cout << sum(a, a+8) << endl; // a[0] to a[7]
12 cout << sum(a+2, a+5) << endl; // a[2] to a[4]
13 cout << sum(&a[2], &a[5]) << endl; // a[2] to a[4]
14}
15
16// Function definition
17// Return the sum of the given array of the range from
18// begin to end, exclude end. 21
19int sum(const int *begin, const int *end) {
20 int sum = 0;
21 for (const int *p = begin; p != end; ++p) {sum += *p;
22 }
23 return sum;
24}
25
Program Notes:
 To write a function that operates on a range of the given array, you can pass the begin
pointer and the end pointer into the function. By convention, the operation shall start at the
begin pointer,up to the end pointer, but excluding the end pointer.
 In "const int *p", *p(content pointed-to) is constant, but p is not constant.
17. *More On Pointers

17.1 Function Pointer


In C/C++, functions, like all data items, have an address. The name of a function is the starting
address where the function resides in the memory, and therefore, can be treated as a pointer. We
can pass a function pointer into function as well. The syntax for declaring a function pointer is:

// Function-pointer declaration
return-type (* function-ptr-name) (parameter-list)

// Examples
double (*fp)(int, int) // fp points to a function that takes two ints and returns a
double (function-pointer)
double *dp; // dp points to a double (double-pointer)
double *fun(int, int) // fun is a function that takes two ints and returns a double-
pointer

double f(int, int); // f is a function that takes two ints and returns a double
fp = f; // Assign function f to fp function-pointer
Example
/* Test Function Pointers (TestFunctionPointer.cpp) */
#include <iostream>
using namespace std;
int arithmetic(int, int, int (*)(int, int));

6 // Take 3 arguments, 2 int's and a function pointer


7 // int (*)(int, int), which takes two int's and return an int
int add(int, int);
int sub(int, int);
int add(int n1, int n2) { return n1 + n2; }
int sub(int n1, int n2) { return n1 - n2; }

22
int arithmetic(int n1, int n2, int (*operation) (int, int)) {return
(*operation)(n1, n2);
}

int main() {
int number1 = 5, number2 = 6;

// add
cout << arithmetic(number1, number2, add) << endl;
// subtract
cout << arithmetic(number1, number2, sub) << endl;
}
17.2 Constant Pointer vs. Constant Pointed-to Data
1. Non-constant pointer to constant data: Data pointed to CANNOT be changed; but pointer
CANbe changed to point to another data. For example,

int i1 = 8, i2 = 9;
const int * iptr = &i1; // non-constant pointer pointing to constant data
// *iptr = 9; // error: assignment of read-only location

iptr = &i2; // okay


2. Constant pointer to non-constant data: Data pointed to CAN be changed; but pointer
CANNOTbe changed to point to another data. For example,

int i1 = 8, i2 = 9;
int * const iptr = &i1; // constant pointer pointing to non-constant data
// constant pointer must be initialized during declaration
*iptr = 9; // okay
// iptr = &i2; // error: assignment of read-only variable
3. Constant pointer to constant data: Data pointed to CANNOT be changed; and pointer
CANNOTbe changed to point to another data. For example,

int i1 = 8, i2 = 9;
const int * const iptr = &i1; // constant pointer pointing to constant data
// *iptr = 9; // error: assignment of read-only variable
// iptr = &i2; // error: assignment of read-only variable
4. Non-constant pointer to non-constant data: Data pointed to CAN be changed; and pointer
CANbe changed to point to another data. For example,
int i1 = 8, i2 = 9; 23
int * iptr = &i1; // non-constant pointer pointing to non-constant data
*iptr = 9; // okay
iptr = &i2; // okay

24
Chapter:9

Classes,Encapsulation

 Classes and Objects


 public, private, protected
 Encapsulation
Class
A class is a user defined data type. A class is a logical abstraction. It is a template that
defines the form of an object. A class specifies both code and data. It is not until an object of
that class has been created that a physical representation of that class exists in memory. When
you define a class, you declare the data that it contains and the code that operates on that data.
Data is contained in instance variables defined by the class known as data members, and code
is contained in functions known as member functions. The code and data that constitute a class
are called members of the class. The general form of class declaration is:
class class-name {
access-specifier:
data and functions
access-specifier:
data and functions
// ...
access-specifier:
data and functions
} object-list;
The object-list is optional. If present, it declares objects of the class. Here, access-specifier is
one of these three C++ keywords:
public private protected
By default, functions and data declared within a class are private to that class and may
be accessed only by other members of the class. The public access_specifier allows functions
or data to be accessible to other parts of your program. The protected access_specifier is needed
only when inheritance is involved.
Example:
#include<iostream.h>
#include<conio.h>
Class myclass { // class declaration
// private members to myclass
int a;
public:
// public members to myclass
void set_a(intnum);
int get_a( );};
Object
An object is an identifiable entity with specific characteristics and behavior. An object
is said to be an instance of a class. Defining an object is similar to defining a variable of any
data type: Space is set aside for it in memory. Defining objects in this way means creating
them. This is also called instantiating them. Once a Class has been declared, we can create
objects of that Class by using the class Name like any other built-in type variable as shown:
className objectName
Example
void main( ) {
myclass ob1, ob2; //these are object of type myclass
// ... program code
}
Accessing Class Members
The main() cannot contain statements that access class members directly. Class
members can be accessed only by an object of that class. To access class members, use the dot
(.) operator. The dot operator links the name of an object with the name of a member. The
general form of the dot operator is shown here:

object. Member

Example
ob1.set_a(10);
The private members of a class cannot be accessed directly using the dot operator, but
through the member functions of that class providing data hiding. A member function can call
another member function directly, without using the dot operator.
C++ program to find sum of two numbers using classes
#include<iostream.h>
#include<conio.h>
class A{
int a,b,c;
public:
void sum(){
cout<<"enter two numbers";
cin>>a>>b;
c=a+b;
cout<<"sum="<<c;
}
};
int main(){
A u;
u.sum();
getch();
return(0);
}
Scope Resolution operator
Member functions can be defined within the class definition or separately using scope
resolution operator (::). Defining a member function within the class definition declares the
function inline, even if you do not use the inline specifier. Defining a member function using
scope resolution operator uses following declaration
return-type class-name::func-name(parameter- list) {
// body of function
}
Here the class-name is the name of the class to which the function belongs. The scope
resolution operator (::) tells the compiler that the function func-name belongs to the class class-
name. That is, the scope of the function is restricted to the class-name specified.
Class myclass {
int a;
public:
void set_a(intnum); //member function declaration
int get_a( ); //member function declaration
};
//member function definition outside class using scope resolution operator
void myclass :: set_a(intnum)
{
a=num;
}
int myclass::get_a( ) {
return a;
}
Another use of scope resolution operator is to allow access to the global version of a
variable. In many Situations, it happens that the name of global variable and the name of the
local variable are same. In this while accessing the variable, the priority is given to the local
variable by the compiler. If we want to access or use the global variable, then the scope
resolution operator (: :) is used. The syntax for accessing a global variable using scope
resolution operator is as follows: -
: Global-variable-name

Static Data Members


When you precede a member variable's declaration with static, you are telling the
compiler that only one copy of that variable will exist and that all objects of the class will share
that variable. Unlike regular data members, individual copies of a static member variable are
not made for each object. No matter how many objects of a class are created, only one copy of
a static data member exists. Thus, all objects of that class use that same variable. All static
variables are initialized to zero before the first
object is created. When you declare a static data member within a class, you are not
defining it. (That is, you are not allocating storage for it.) Instead, you must provide a global
definition for it elsewhere, outside the class. This is done by redeclaring the static variable
using the scope resolution operator to identify the class to which it belongs. This causes storage
for the variable to be allocated.
One use of a static member variable is to provide access control to some shared resource
used by all objects of a class. Another interesting use of a static member variable is to keep
track of the number of objects of a particular class type that are in existence.

Static Member Functions


Member functions may also be declared as static. They may only directly refer to other
static members of the class. Actually, static member functions have limited applications, but
one good use for them is to "preinitialize" private static data before any object is actually
created.
A static member function can be called using the class name instead of its objects as
follows:
class name :: function name

//Program showing working of static class members


#include <iostream.h>
#include<conio.h>
class static_type {
static int i; //static data member
public:
static void init(int x) {i = x;} //static member function
void show() {cout << i;}};
int static_type :: i; // static data member definition
int main(){
static_type::init(100); //Accessing static function
static_type x;
x.show();
return 0;
}
Encapsulation in C++ with example

Encapsulation is a process of combining data members and functions in a single unit


called class. This is to prevent the access to the data directly, the access to them is provided
through the functions of the class. It is one of the popular feature of Object Oriented
Programming(OOPs) that helps in data hiding.

How Encapsulation is achieved in a class

To do this:
1) Make all the data members private.
2) Create public setter and getter functions for each data member in such a way that the set
function set the value of data member and get function get the value of data member.

Let‟s see this in an example Program:

Encapsulation Example in C++

Here we have two data members num and ch, we have declared them as private so that they
are not accessible outside the class, this way we are hiding the data. The only way to get and
set the values of these data members is through the public getter and setter functions.

#include<iostream>
using namespace std;
class ExampleEncap{
private:
/* Since we have marked these data members private,
* any entity outside this class cannot access these
* data members directly, they have to use getter and
* setter functions.
*/
int num;
char ch;
public:
/* Getter functions to get the value of data members.
* Since these functions are public, they can be accessed
* outside the class, thus provide the access to data members
* through them
*/
int getNum() const {
return num;
}
char getCh() const {
return ch;
}
/* Setter functions, they are called for assigning the values
* to the private data members.
*/
void setNum(int num) {
this->num = num;
}
void setCh(char ch) {
this->ch = ch;
}
};
int main(){
ExampleEncap obj;
obj.setNum(100);
obj.setCh('A');
cout<<obj.getNum()<<endl;
cout<<obj.getCh()<<endl;
return 0;
}
Output:

100
A
Chapter:10 Constructors

 Constructors and destructors


 Overloaded Constructor
 Copy Constructor
 Shallow Copying Deep Copying.
Constructor:
A constructor is a special member function whose task is to initialize the objects
of its class. It is special because its name is same as the class name. The constructor is
invoked whenever an object of its associated class is created. It is called constructor
because it construct the value data members of the class. The constructor functions have
some special characteristics.
They should be declared in the public section.
They are invoked automatically when the objects are created.
They do not have return types, not even void and therefore, they cannot return
values.
They cannot be inherited, though a derived class can call the base class
constructor.
Example:
#include< iostream.h>
#include<conio.h>
class myclass { // class declaration
int a;
public:
myclass( ); //default constructor
void show( );
};
myclass :: myclass( ) {
cout <<"In constructor\n";
a=10;
}
myclass :: show( ) {
cout<< a;
}
int main( ) {
int ob; // automatic call to constructor
ob.show( );
return0;}
In this simple example the constructor is called when the object is created, and
the constructor initializes the private variable a to10.
Default constructor
The default constructor for any class is the constructor with no arguments. When
no arguments are passed, the constructor will assign the values specifically assigned in
the body of the constructor. It can be zero or any other value. The default constructor
can be identified by the name of the class followed by empty parentheses. Above
program uses default constructor. If it is not defined explicitly, then it is automatically
defined implicitly by the system.
Parameterized Constructor
It is possible to pass arguments to constructors. Typically, these arguments help
initialize an object when it is created. To create a parameterized constructor, simply add
parameters to it the way you would to any other function. When you define the
constructor's body, use the parameters to initialize the object.
#include <iostream.h>
#include<conio.h>
class myclass {
int a, b;
public:
myclass(int i, int j) //parameterized constructor
{a=i; b=j;}
void show() { cout << a << " " << b;}
};
int main() {
myclass ob(3, 5); //call to constructor
ob.show();
return 0;
}
C++ supports constructor overloading. A constructor is said to be overloaded
when the same constructor with different number of argument and types of arguments
initializes an object.
Copy Constructors
The copy constructor is a constructor which creates an object by initializing it
with an object of the same class, which has been created previously. If class definition
does not explicitly include copy constructor, then the system automatically creates one
by default. The copy constructor is used to:
Initialize one object from another of the same type.
Copy an object to pass it as an argument to a function.
Copy an object to return it from a function.
The most common form of copy constructor is shown here:
classname (const classname &obj) {
// body of constructor
}
Here, obj is a reference to an object that is being used to initialize another object. The
keyword const is used because obj should not be changed.

Deep Copy and Shallow Copy in C++


The definition of deep copy and shallow copy is given below:

Creating a copy of object by copying data of all member variables as it is, is


called shallow copy while creating an object by copying data of another object along with the
values of memory resources resides outside the object but handled by that object, is
called deep copy.

Let us first understand some basic points that you should aware of before knowing
about shallow copy and deep copy in details.
How can we create a copy of an object?
1. Default copy constructor is defined by the compiler when object of any class is
created and there is no copy constructor defined in the program.

2. In addition to copy constructor, C++ compiler also overload copy assignment


operator which is implemented when an object (after declaration) is initialized using "=" with
another object of same class.
For Example:- copy assignment operator in c++

#include<iostream>

using namespace std;

class DummyClass

private:

int num1, num2;

public:

void setData(int x, int y)

num1 = x;

num2 = y;

void showData()

cout << num1 << " " << num2 << endl;

};

int main()

DummyClass D1;
D1.setData(5, 11);
D1.showData();

//Copy constructor (created by compiler) will came in action here.


DummyClass D2 = D1;
D2.showData();

DummyClass D3;
D3.setData(1, 11);
D3.showData();

DummyClass D4;

//Copy assignment operator overloaded by compiler came in action.


D4 = D3;
D4.showData();

return 0;

Output:

5 11

5 11

1 11

1 11
In the above example, object D4 is created and then it is initialized with object D3. In
this case, copy assignment operator which is overloaded by compiler itself is implemented.

Points To Remember:-

When we create a copy of an object:

1. copy constructor will be called or

2. implicit copy assignment operator will be called.

When will Copy Constructor call?

When you initialize an object with another object of same class during its
declaration, copy constructor will be called.

For Example:-

#include<iostream>

using namespace std;

class DummyClass {

private:

int num1, num2;

public:

void setData(int x, int y) {

num1 = x;

num2 = y;
}

void showData() {

cout << num1 << " " << num2 << endl;

};

int main() {

DummyClass D1;

D1.setData(5, 11);

D1.showData();

//Copy constructor (created by compiler) will came in action here.

DummyClass D2 = D1;

D2.showData();

When will Copy Assignment Operator call?


When you do not initialize an object during its declaration but initialize it after its declaration
with another object of same class then copy assignment operator will be called.

For Example:-

#include<iostream>

using namespace std;


class DummyClass {

private:

int num1, num2;

public:

void setData(int x, int y) {

num1 = x;

num2 = y;

void showData() {

cout << num1 << " " << num2 << endl;

};

int main() {

DummyClass D1;

D1.setData(5, 11);

D1.showData();

DummyClass D2;

//Copy assignment operator overloaded by compiler came in action.

D2 = D1;

D4.showData();

}
Deep Copy and Shallow Copy in C++
1. Creating a copy of object by copying data of all member variables as it is, it is
called shallow copy. The compiler will do shallow copy by default.

2. Creating an object by copying data of another object along with the values of memory
resources resides outside the object but handled by that object, it is called deep copy.

For Example:- deep copy and shallow copy in c++

#include<iostream>

using namespace std;

class DummyClass {

private:

int num1, num2;

int *ptr;

public:

DummyClass() {

ptr = new int;

void setData(int x, int y, int z) {

num1 = x;

num2 = y;

*ptr = z;
}

void showData() {

cout << "A = " << num1 << " B = " << num2 << endl;

//copy constructor -> it is responsible for deep copy.

DummyClass(DummyClass &D) {

num1 = D.num1;

num2 = D.num2;

*ptr = *(D.ptr);

//destructor -> to deallocate memory consumed by new pointer ptr.

~DummyClass() {

delete ptr;

};

int main() {

DummyClass D1;

D1.setData(3, 5, 11);

D1.showData();

//Copy constructor declared above will came in action and do deep copy.
DummyClass D2 = D1;

D2.showData();

Output:

A=3 B=5

A=3 B=5

What is Dangling Pointer in C++?


A pointer which is pointing to an invalid address is called dangling pointer. There is a chance
of program crash due to dangling pointer.
Destructor
A destructor destroys an object after it is no longer in use. The destructor, like
constructor, is a member function with the same name as the class name. But it will be
preceded by the character Tilde (~).A destructor takes no arguments and has no return
value. Each class has exactly one destructor. . If class definition does not explicitly
include destructor, then the system automatically creates one by default. It will be
invoked implicitly by the compiler upon exit from the program to clean up storage that
is no longer accessible.
// A Program showing working of constructor and destructor
#include<iostream.h>
#include<conio.h>
class Myclass{
public:
int x;
Myclass(){ //Constructor
x=10; }
~Myclass(){ //Destructor
cout<<”Destructing….” ;
}
int main(){
Myclass ob1, ob2;
cout<<ob1.x<<” “<<ob2.x;
return 0; }
Output:
10 10
Destructing……..
Destructing……..
Chapter:11 Friend Function

 Overloading-this' Pointer
 Structs vs Classes
 Friends of a class
 Operator Overloading
Friend function

In general, only other members of a class have access to the private members of
the class. However, it is possible to allow a non-member function access to the private
members of a class by declaring it as a friend of the class. To make a function a friend
of a class, you include its prototype in the class declaration and precede it with the
friend keyword. The function is declared with friend keyword. But while defining
friend function, it does not use either keyword friend or :: operator. A function can be
a friend of more than one class. Member function of one class can be friend functions
of another class.
In such cases they are defined using the scope resolution operator.
A friend, function has following characteristics.
It is not in the scope of the class to which it has been declared as friend.
A friend function cannot be called using the object of that class. If can be invoked
like a normal function without help of any object.
It cannot access the member variables directly & has to use an object name dot
membership operator with member name.
It can be declared either in the public or the private part of a class without affecting
its meaning.
Usually, it has the object as arguments.
Program to illustrate use of friend function
#include<iostream.h>
#include<conio.h>
class A{
int x, y;
public:
friend void display(A &obj);
void getdata() {
cin>>x>>y;
}
};
void display(A &obj){
cout<<obj.x<<obj.y;
}
int main(){
A a;
a.getdata();
display(a);
getch();
return 0;
}

Operator overloading
There is another useful methodology in C++ called operator overloading. The
language allows not only functions to be overloaded, but also most of the operators,
such as +, -, *, /, etc. As the name suggests, here the conventional operators can be
programmed to carry out more complex operations.
This overloading concept is fundamentally the same i.e. the same operators can
be made to perform different operations depending on the context. Such operators have
to be specifically defined and appropriate function programmed. When an operator is
overloaded, none of its original meaning is lost. It is simply that a new operation,
relative to a specific class, is defined. For example, a class that defines a linked list
might use the + operator to add an object to the list. A class that implements a stack
might use the + to push an object onto the stack.
An operator function defines the operations that the overloaded operator will
perform relative to the class upon which it will work. An operator function is created
using the keyword operator. The general form of an operator function is
type classname::operator#(arg-list) { // operations
}
Here, the operator that you are overloading is substituted for the #, and type is
the type of value returned by the specified operation. Operator functions can be either
members or non-members of a class. Non-member operator functions are often friend
functions of the class.
These operators cannot be overloaded:- ., : :, .*, ?
The process of overloading involves the following steps:
Create a class that defines the data type that is to be used in the overloading operation.
Declare the operator function operator op() in the public part of the class.
Define the operator function to implement the required operations.
Overloading a unary operator using member function
Overloading a unary operator using a member function, the function takes no
parameters. Since, there is only one operand, it is this operand that generates the call to
the operator function. There is no need for another parameter.
Overloading unary minus operator
#include<iostream.h>
#include<conio.h>
class A {
int x,y,z;
public:
void getdata(int a,int b,int c) {
x=a;
y=b;
z=c;
}
void display() {
cout<<"\nx="<<x<<"\ny="<<y<<"\nz="<<z;
}
void operator -() //unary minus overload function
{
x=-x;
y=-y;
z=-z;
}
};
int main() {
A a;
a.getdata(2,3,4);
a.display();
-a; //activates operator –() function
a.display();
getch();
return 0;
}

Overloading binary operator


When a member operator function overloads a binary operator, the function will
have only one parameter. This parameter will receive the object that is on the right side
of the operator. The object on the left side is the object that generates the call to the
operator function and is passed implicitly by this pointer. „this‟ can be used in
overloading + operator .
#include<iostream.h>
#include<conio.h>
class A{
int x,y;
public:
void input() {
cin>>x>>y;
}
void display() {
cout<<"\nx="<<x<<"\ny="<<y<<"\nx+y="<<x+y;
}
A operator+(A p ); //overload binary + operator
};
A A :: operator+(A p) {
A t;
t.x=x + p.x;
t.y=y + p.y;
return t;
}
int main(){
A a1, a2, a3;
a1.input();
a2.input();
a3=a2+a1; //activates operator+() function
a3.display();
getch();
return 0;
}
this Pointer
It is facilitated by another interesting concept of C++ called this pointer. „this‟
is a C++ keyword. „this‟ always refers to an object that has called the member function
currently. We can say that „this‟ is a pointer. It points to the object that has called this
function this time. While overloading binary
operators, we use two objects, one that called the operator function and the
other, which is passed to the function. We referred to the data member of the calling
object, without any prefix. However, the data member of the other object had a prefix.
Always „this‟ refers to the calling object place of the object name.
Chapter:12 Inheritance

 Inheritance
 Overloading vs overriding
Inheritance
Inheritance is the mechanism by which one class can inherit the properties of
another. It allows a hierarchy of classes to be build, moving from the most general to
the most specific. When one class is inherited by another, the class that is inherited is
called the base class. The inheriting class is called the derived class. In general, the
process of inheritance begins with the definition of a base class. The base class defines
all qualities that will be common to any derived class. In essence, the base class
represent the most general description of a set of traits. The derived class inherits those
general traits and adds properties that are specific to that class. When one class inherits
another, it uses this general
form:
class derived-class-name : access base-class-name{
// ...
}
Here access is one of the three keywords: public, private, or protected. The
access specifier determines how elements of the base class are inherited by the derived
class. When the access specifier for the inherited base class is public, all public
members of the base class become public members of the derived class. If the access
specifier is private, all public members of the base class become private members of
the derived class. In either case, any private members of the base class remain private
to it and are inaccessible by the derived class.
It is important to understand that if the access specifier is private, public
members of the base become private members of the derived class. If the access
specifier is not present, it is private by default.
The protected access specifier is equivalent to the private specifier with the sole
exception that
protected members of a base class are accessible to members of any class
derived from that base. Outside the base or derived classes, protected members are not
accessible. When a protected member of a base class is inherited as public by the
derived class, it becomes a protected member of the derived class. If the base class is
inherited as private, a protected member of the base becomes a private member of the
derived class. A base class can also be inherited as protected by a derived class.
When this is the case, public and protected members of the base class become
protected members of the derived class (of course, private members of the base remain
private to it and are not accessible by the derived class).
Program to illustrate concept of inheritance
#include<iostream.h>
#include<conio.h>
class base //base class
{
int x,y;
public:
void show() {
cout<<"In base class";
}
};
class derived : public base //derived class
{
int a,b;
public:
void show2() {
cout<<"\nIn derived class";
}
};
int main() {
derived d;
d.show(); //uses base class‟s show() function
d.show2(); //uses derived class‟s show2() function
getch();
return 0;
}
Types of Inheritances
Single Inheritance
The process in which a derived class inherits traits from only one base class, is called
single inheritance. In single inheritance, there is only one base class and one derived class. The
derived class inherits the behavior and attributes of the base class. However the vice versa is
not true. The derivedclass can add its own properties i.e. data members (variables) and
functions. It can extend or use properties of the base class without any modification to the base
class. We declare the base class and derived class as given below:
class base_class {
};
class derived_ class : visibility-mode base_ class {
};
Program to illustrate concept of single inheritance
#include<iostream.h>
#include<conio.h>
class base //base class
{
int x,y;
public:
void show() {
cout<<"In base class";
}
};
class derived : public base //derived class
{
int a,b;
public:
void show2() {
cout<<"\nIn derived class";
}
};
int main() {
derived d;
d.show(); //uses base class‟s show() function
d.show2(); //uses derived class‟s show2() function
getch();

return 0;
}
Ambiguity in single Inheritance
Whenever a data member and member functions are defined with the same
name in both the base and derived class, ambiguity occurs. The scope resolution
operator must be used to refer to particular class
as: object name.class name :: class member
Multiple Inheritance
The process in which a derived class inherits traits from several base classes, is
called multiple inheritance. In Multiple inheritance, there is only one derived class and
several base classes. We declare the base classes and derived class as given below:
class base_class1{
};
class base_class2{
};
class derived_ class : visibility-mode base_ class1 , visibility-mode base_
class2 {
};
Multilevel Inheritance
The process in which a derived class inherits traits from another derived class,
is called Multilevel Inheritance. A derived class with multilevel inheritance is declared
as :
class base_class {
};
class derived_ class1 : visibility-mode base_ class {
};
class derived_ class 2: visibility-mode derived_ class1 {
};
Here, derived_ class 2 inherits traits from derived_ class 1 which itself inherits
from base_class.
Hierarchical Inheritance
The process in which traits of one class can be inherited by more than one class
is known as Hierarchical inheritance. The base class will include all the features that
are common to the derived classes. A derived class can serve as a base class for lower
level classes and so on.
Hybrid Inheritance
The inheritance hierarchy that reflects any legal combination of other types of
inheritance is known as hybrid Inheritance.
Overriding
Overriding is defined as the ability to change the definition of an inherited
method or attribute in a derived class. When multiple functions of the same name exist
with different signatures it is called function overloading. When the signatures are the
same, they are called function overriding. Function
overriding allows a derived class to provide specific implementation of a
function that is already provided by a base class. The implementation in the derived
class overrides or replaces the implementation in the corresponding base class.
Virtual base classes
A potential problem exists when multiple base classes are directly inherited by
a derived class. To understand what this problem is, consider the following class
hierarchy:
Here the base class Base is inherited by both Derived1and Derived2. Derived3
directly inherits both Derived1and Derived2.However, this implies that Base is actually
inherited twice by Derived3.First it is inherited through Derived1, and then again
through Derived2.This causes ambiguity when a member of Base is used by Derived3.
Since two copies of Base are included in Derived3, is a reference to a member of Base
referring to the Base inherited indirectly through Derived1or to the Base inherited
indirectly through Derived2? To resolve this ambiguity, C++ includes a mechanism by
which only one copy of Base will be included in Derived3. This feature is called a
virtual base class.
In situations like this, in which a derived class indirectly inherits the same base
class more than once, it is possible to prevent multiple copies of the base from being
present in the derived class by having that base class inherited as virtual by any derived
classes. Doing this prevents two or more copies of the base from being present in any
subsequent derived class that inherits the base class indirectly. The virtual keyword
precedes the base class access specifier when it is inherited by a derived class.
// This program uses a virtual base class.
#include <iostream>
using namespace std;
class Base {
public:
int i;
};
// Inherit Base as virtual
classDerived1 : virtual publicBase {
public:
int j;
};
// Inherit Base as virtual here, too
classDerived2 : virtual publicBase {
public:
int k;
};
// Here Derived3 inherits both Derived1 and Derived2.
// However, only one copy of base is inherited.
class Derived3 : publicDerived1, publicDerived2 {
public:
int product( ) { return i*j*k; }
};
int main( ) {
Derived3 ob;
ob.i = 10; // unambiguous because virtual Base
ob.j = 3;
ob.k = 5;
cout << "Product is: " << ob.product( ) << "\n";
return 0;
}
If Derived1and Derived2 had not inherited Base as virtual, the statement
ob.i=10 would have been ambiguous and a compile-time error would have resulted. It
is important to understand that when a base class is inherited as virtual by a derived
class, that base class still exists within that derived class.
For example, assuming the preceding program, this fragment is perfectly valid:
Derived1 ob;
ob.i = 100;
Friend Classes
It is possible for one class to be a friend of another class. When this is the case,
the friend class and all of its member functions have access to the private members
defined within the other class. For
example,
// Using a friend class.
#include<iostream.h>
#include<conio.h>
class A{
int x, y;
public:
friend void display(A &obj);
friend class B;
void getdata() {
cin>>x>>y;
}
};
class B{
int p,q;
public:
void get(A &obj) {
p=obj.x;
q=obj.y;
}
};
void display(A &obj){
cout<<obj.x<<obj.y;

}
int main(){
A a;
B b;
b.get(a);
a.getdata();
display(a);
getch();
return 0;
}
It is critical to understand that when one class is a friend of another, it only has
access to names defined within the other class. It does not inherit the other class.
Specifically, the members of the first class do not become members of the friend class.
Chapter:13 Polymorphism

 Polymorphism
 Virtual Functions
 Pure Virtual Functions and
Abstract Classes.
Polymorphism in C++
The word polymorphism means having many forms. In simple words, we can define
polymorphism as the ability of a message to be displayed in more than one form.
Real life example of polymorphism, a person at the same time can have different
characteristic. Like a man at the same time is a father, a husband, an employee. So the same
person posses different behavior in different situations. This is called polymorphism.
Polymorphism is considered as one of the important features of Object Oriented
Programming.
In C++ polymorphism is mainly divided into two types:
 Compile time Polymorphism
 Runtime Polymorphism

1. Compile time polymorphism: This type of polymorphism is achieved by function


overloading or operator overloading.

 Function Overloading: When there are multiple functions with same name but
different parameters then these functions are said to be overloaded. Functions can
be overloaded by change in number of arguments or/and change in type of
arguments.

// C++ program for function


overloading #include
<bits/stdc++.h>

using namespace
std; class Geeks
{
public:

// function with 1 int


parameter void func(int x)
{
cout << "value of x is " << x << endl;

// function with same name but 1 double


parameter void func(double x)
{
cout << "value of x is " << x << endl;
}

// function with same name and 2 int


parameters void func(int x, int y)
{
cout << "value of x and y is " << x << ", " << y << endl;
}
};

int main() {

Geeks

obj1;

// Which function is called will depend on the parameters passed


// The first 'func' is
called obj1.func(7);

// The second 'func' is


called obj1.func(9.132);

// The third 'func' is called


obj1.func(85,64);
return 0;
}
Output:
value of x is 7
value of x is 9.132
value of x and y is 85, 64

In the above example, a single function named func acts differently in three
different situations which is the property of polymorphism.

 Operator Overloading: C++ also provide option to overload operators. For


example, we can make the operator („+‟) for string class to concatenate two
strings. We know that this is the addition operator whose task is to add two
operands. So a single operator „+‟ when placed between integer operands , adds
them and when placed between string operands, concatenates them.
Example:
// CPP program to illustrate
// Operator
Overloading
#include<iostream>
using namespace
std;

class
Complex {
private:
int real,
imag; public:
Complex(int r = 0, int i =0) {real = r; imag = i;}
// This is automatically called when '+' is used with
// between two Complex objects
Complex operator + (Complex const &obj) {
Complex res;
res.real = real +
obj.real; res.imag =
imag + obj.imag; return
res;
}
void print() { cout << real << " + i" << imag << endl; }
};

int main()
{
Complex c1(10, 5), c2(2, 4);
Complex c3 = c1 + c2; // An example call to
"operator+" c3.print();
}
Output:
12 + i9
In the above example the operator „+‟ is overloaded. The operator „+‟ is an
addition operator and can add two numbers(integers or floating point) but here the
operator is made to perform addition of two imaginary or complex numbers. To
learn operator overloading in details visit this link.

2. Runtime polymorphism: This type of polymorphism is achieved by Function


Overriding.
 Function overriding on the other hand occurs when a derived class has a
definition for one of the member functions of the base class. That base function is
said to be overridden.
// C++ program for function overriding

#include
<bits/stdc++.h>
using namespace
std;

class base
{
public:
virtual void print ()
{ cout<< "print base class" <<endl; }

void show ()
{ cout<< "show base class" <<endl; }
};

class derived:public base


{
public:
void print () //print () is already virtual function in derived class,
//we could also declared as virtual void print () explicitly
{ cout<< "print derived class" <<endl; }

void show ()
{ cout<< "show derived class" <<endl; }
};

//main
function int
main()
{
base
*bptr;
derived
d; bptr =
&d;

//virtual function, binded at runtime (Runtime


polymorphism) bptr->print();

// Non-virtual function, binded at


compile time bptr->show();

return 0;
}
Output:
print derived class
show base class
Virtual Function in C++
A virtual function is a member function which is declared within a base class and is re-
defined(Overriden) by a derived class. When you refer to a derived class object using a
pointer or a reference to the base class, you can call a virtual function for that object and
execute the derived class‟s version of the function.
 Virtual functions ensure that the correct function is called for an object, regardless of
the type of reference (or pointer) used for function call.
 They are mainly used to achieve Runtime polymorphism
 Functions are declared with a virtual keyword in base class.
 The resolving of function call is done at Run-time.

Rules for Virtual Functions


1. Virtual functions cannot be static and also cannot be a friend function of another class.
2. Virtual functions should be accessed using pointer or reference of base class type to
achieve run time polymorphism.
3. The prototype of virtual functions should be same in base as well as derived class.
4. They are always defined in base class and overridden in derived class. It is not
mandatory for derived class to override (or re-define the virtual function), in that case
base class version of function is used.
5. A class may have virtual destructor but it cannot have a virtual constructor.

Compile-time(early binding) VS run-time(late binding) behavior of Virtual Functions


Consider the following simple program showing run-time behavior of virtual functions.
// CPP program to illustrate
// concept of Virtual Functions

#include
<iostream> using
namespace std;

class base
{ public:
virtual void print()
{
cout << "print base class" << endl;
}

void show()
{
cout << "show base class" << endl;
}
};

class derived : public


base { public:
void print()
{
cout << "print derived class" << endl;
}

void show()
{
cout << "show derived class" << endl;
}
};

int main()
{
base*
bptr;
derived
d; bptr =
&d;

// virtual function, binded at


runtime bptr->print();

// Non-virtual function, binded at


compile time bptr->show();
}
Output:
print derived class
show base class

Explanation: Runtime polymorphism is achieved only through a pointer (or reference) of


base class type. Also, a base class pointer can point to the objects of base class as well as to
the objects of derived class. In above code, base class pointer „bptr‟ contains the address of
object „d‟ of derived class.
Late binding(Runtime) is done in accordance with the content of pointer (i.e. location pointed
to by pointer) and Early binding(Compile time) is done according to the type of pointer, since
print() function is declared with virtual keyword so it will be bound at run-time (output
is print derived class as pointer is pointing to object of derived class ) and show() is non-
virtual so it will be bound during compile time(output is show base class as pointer is of base
type ).

NOTE: If we have created a virtual function in the base class and it is being overridden in the
derived class then we don‟t need virtual keyword in the derived class, functions are
automatically considered as virtual functions in the derived class.
Working of virtual functions(concept of VTABLE and VPTR)
As discussed here, If a class contains a virtual function then compiler itself does two things:
1. If object of that class is created then a virtual pointer(VPTR) is inserted as a data
member of the class to point to VTABLE of that class. For each new object created, a
new virtual pointer is inserted as a data member of that class.
2. Irrespective of object is created or not, a static array of function pointer called
VTABLE where each cell contains the address of each virtual function contained in
that class.
Consider the example below:

// CPP program to illustrate


// working of Virtual
Functions#include
<iostream>
using namespace std;

class base
{public:
void fun_1() { cout << "base-1\n"; }
virtual void fun_2() { cout << "base-
2\n"; } virtual void fun_3() { cout <<
"base-3\n"; } virtual void fun_4() { cout
<< "base-4\n"; }
};

class derived : public base {


public:
void fun_1() { cout << "derived-1\n"; }
void fun_2() { cout << "derived-2\n"; }
void fun_4(int x) { cout << "derived-
4\n"; }
};

int main()
{
base* p;
derived
obj1;
p = &obj1;

// Early binding because fun1() is non-virtual


// in base
p->fun_1();

// Late binding
(RTP)p->fun_2();

// Late binding
(RTP)p->fun_3();

// Late binding
(RTP)p->fun_4();

// Early binding but this function call is


// illegal(produces error) becasue pointer
// is of base type and function is of
// derived class
// p->fun_4(5);
}
Output:
base-1
derived-2
base-3
base-4

Explanation: Initially, we create a pointer of type base class and initialize it with the address
of the derived class object. When we create an object of the derived class, the compiler
creates a pointer as a data member of the class containing the address of VTABLE of the
derived class.
Similar concept of Late and Early Binding is used as in above example. For fun_1()
function call, base class version of function is called, fun_2() is overridden in derived class so
derived class version is called, fun_3() is not overridden in derived class and is virtual
function so base class version is called, similarly fun_4() is not overridden so base class
version is called.

NOTE: fun_4(int) in derived class is different from virtual function fun_4() in base class as prototype
of both the function is different.

A pure virtual function (or abstract function) in C++ is a virtual function for which we don‟t
have implementation, we only declare it. A pure virtual function is declared by assigning 0 in
declaration. See the following example.
// An abstract
classclass Test
{
// Data members of
classpublic:
// Pure Virtual Function
virtual void show() = 0;

/* Other members */
};
A complete example:

A pure virtual function is implemented by classes which are derived from a Abstract class.
Following is a simple example to demonstrate the same.

#include<iostream>
using namespace std;

class Base
{
int
x;
public
:
virtual void fun() = 0;
int getX() { return x;
}
};

// This class inherits from Base and implements


fun()class Derived: public Base
{
int
y;
public:
void fun() { cout << "fun() called"; }
};

int main(void)
{
Derived
d;d.fun();
return 0;
}
Output:
fun() called
Chapter:14 Abstract Classes

 Abstract Classes as Interfaces


Abstract class

By definition, an abstract class in C++ is a class that has at least one pure virtual
function (i.e., a function that has no definition). The classes inheriting the abstract
class must provide a definition for the pure virtual function; otherwise, the subclass would
become an abstract class itself.

Abstract classes are essential to providing an abstraction to the code to make it


reusable and extendable. For example, a Vehicle parent class
with Truck and Motorbike inheriting from it is an abstraction that easily allows more vehicles
to be added. However, even though all vehicles have wheels, not all vehicles have the same
number of wheels – this is where a pure virtual function is needed.

Consider an example of a Shape base class with sub-classes (Triangle and Rectangle)
that inherit the Shape class.

Now, suppose we need a function to return the area of a shape. The function will be
declared in the Shape class; however, it cannot be defined there as the formula for the area is
different for each shape. A non-specific shape does not have an area, but rectangles and
triangles do. Therefore, the pure virtual function for calculating area will be implemented
differently by each sub-class.
The following code snippet implements the abstract Shape class along with its sub-classes:

#include <iostream>

using namespace std;

class Shape {
public:
virtual int Area() = 0; // Pure virtual function is declared as follows.
// Function to set width.
void setWidth(int w) {
width = w;
}
// Function to set height.
void setHeight(int h) {
height = h;
}

protected:
int width;
int height;
};

// A rectangle is a shape; it inherits shape.


class Rectangle: public Shape {
public:
// The implementation for Area is specific to a rectangle.
int Area() {
return (width * height);
}
};
// A triangle is a shape too; it inherits shape.
class Triangle: public Shape {
public:
// Triangle uses the same Area function but implements it to
// return the area of a triangle.
int Area() {
return (width * height)/2;
}
};

int main() {
Rectangle R;
Triangle T;

R.setWidth(5);
R.setHeight(10);

T.setWidth(20);
T.setHeight(8);

cout << "The area of the rectangle is: " << R.Area() << endl;
cout << "The area of the triangle is: " << T.Area() << endl;
}
Chapter:15
Exception and File Handling

 Exception
 Files, Streams
 I/O
1
C++ Exception Handling

An exception is a problem that arises during the execution of a program. A C++ exception is a response to
an exceptional circumstance that arises whilea program is running, such as an attempt to divide by zero.

Exceptions provide a way to transfer control from one part of a program to another. C++ exception
handling is built upon three keywords: try, catch, and throw.

throw: A program throws an exception when a problem shows up. This is done using a throw
keyword.

catch: A program catches an exception with an exception handler at the place in a program where
you want to handle the problem. The catch keyword indicates the catching of an exception.

try: A try block identifies a block of code for which particular exceptions will be activated. It's
followed by one or more catch blocks.

Assuming a block will raise an exception, a method catches an exception usinga combination of the try and
catch keywords. A try/catch block is placed around the code that might generate an exception. Code within
a try/catch block is referred to as protected code, and the syntax for using try/catch lookslike the following:

try

// protected code

}catch( ExceptionName e1 )

1
// catch block

}catch( ExceptionName e2 )

// catch block

}catch( ExceptionName eN )

// catch block

You can list down multiple catch statements to catch different type of exceptions in case your try block
raises more than one exception in different situations.

ThrowingExceptions:
Exceptions can be thrown anywhere within a code block using throw statements. The operand of the throw
statements determines a type for the exception and can be any expression and the type of the result of the
expression determines the type of exception thrown.

Following is an example of throwing an exception when dividing by zero condition occurs:

double division(int a, int b)

if( b == 0 )

throw "Division by zero condition!";

return (a/b);

2
}

Catching Exceptions:
The catch block following the try block catches any exception. You can specifywhat type of exception you
want to catch and this is determined by the exception declaration that appears in parentheses following the
keyword catch.

try

// protected code

}catch(
try ExceptionName e )

{
{
//
//code to handle
protected codeExceptionName exception
}
}catch(...)

// code to handle any exception

Above code will catch an exception of ExceptionName type. If you want to specify that a catch block
should handle any type of exception that is thrownin a try block, you must put an ellipsis, ..., between the
parentheses enclosing the exception declaration as follows:

3
The following is an example, which throws a division by zero exception and wecatch it in catch block.

#include <iostream>

using namespace std;

double division(int a, int b)

if( b == 0 )

throw "Division by zero condition!";

return (a/b);

int main ()

int x = 50;

int y = 0;

double z = 0;

try {

z = division(x, y);

4
cout << z << endl;

}catch (const char* msg) {

cerr << msg << endl;

5
return 0;

Because we are raising an exception of type const char*, so while catching this exception, we have to use
const char* in catch block. If we compile and run above code, this would produce the following result:

Division by zero condition!

6
C++StandardExceptions:
C++ provides a list of standard exceptions defined in <exception> which we can use in our programs.
These are arranged in a parent-child class hierarchy shown below:

Here is the small description of each exception mentioned in the abovehierarchy:

Exception Description

std::exception An exception and parent class of all the standard C++ exceptions.

7
std::bad_alloc This can be thrown by new.

std::bad_cast This can be thrown by dynamic_cast.

std::bad_exception This is useful device to handle unexpected exceptions in a C++


program

std::bad_typeid This can be thrown by typeid.

std::logic_error An exception that theoretically can be detected by reading thecode.

std::domain_error This is an exception thrown when a mathematically invalid domainis


used

std::invalid_argument This is thrown due to invalid arguments.

std::length_error This is thrown when a too big std::string is created

std::out_of_range This can be thrown by the at method from for example a std::vectorand
std::bitset<>::operator[]().

std::runtime_error An exception that theoretically can not be detected by reading thecode.

std::overflow_error This is thrown if a mathematical overflow occurs.

std::range_error This is occured when you try to store a value which is out of range.

std::underflow_error This is thrown if a mathematical underflow occurs.

8
DefineNewExceptions:
You can define your own exceptions by inheriting and overriding exception class functionality. Following
is the example, which shows how you can use std::exception class to implement your own exception in
standard way:

#include <iostream>

#include <exception>

using namespace std;

struct MyException : public exception

const char * what () const throw ()

return "C++ Exception";

};

int main()

try

throw MyException();

catch(MyException& e)

std::cout << "MyException caught" << std::endl;

std::cout << e.what() << std::endl;

9
}

catch(std::exception& e)

//Other errors

This would produce the following result:

MyException caught

C++ Exception

Here, what() is a public method provided by exception class and it has been overridden by all the child
exception classes. This returns the cause of an exception.

10
2
C++ Templates

Templates are the foundation of generic programming, which involves writing code in a way that is
independent of any particular type.

A template is a blueprint or formula for creating a generic class or a function. The library containers like
iterators and algorithms are examples of generic programming and have been developed using template
concept.

There is a single definition of each container, such as vector, but we candefine many different kinds
of vectors for example, vector <int> or vector
<string>.

You can use templates to define functions as well as classes, let us see how dothey work:

FunctionTemplate:
The general form of a template function definition is shown here:

template <class type> ret-type func-name(parameter list)

// body of function

Here, type is a placeholder name for a data type used by the function. Thisname can be used within the
function definition.

The following is the example of a function template that returns the maximumof two values:

#include <iostream>

#include <string>

11
using namespace std;

template <typename T>

inline T const& Max (T const& a, T const& b)

return a < b ? b:a;

int main ()

int i = 39;

int j = 20;

cout << "Max(i, j): " << Max(i, j) << endl;

double f1 = 13.5;

double f2 = 20.7;

cout << "Max(f1, f2): " << Max(f1, f2) << endl;

string s1 = "Hello";

string s2 = "World";

cout << "Max(s1, s2): " << Max(s1, s2) << endl;

12
return 0;

If we compile and run above code, this would produce the following result:

13
Max(i, j): 39

Max(f1, f2): 20.7

Max(s1, s2): World

ClassTemplate:
Just as we can define function templates, we can also define class templates.The general form of a generic
class declaration is shown here:

template <class type> class class-name {

Here, type is the placeholder type name, which will be specified when a class is instantiated. You can
define more than one generic data type by using a comma-separated list.

Following is the example to define class Stack<> and implement generic methods to push and pop the
elements from the stack:

#include <iostream>

#include <vector>

#include <cstdlib>

#include <string>

#include <stdexcept>

using namespace std;

14
template <class T>

class Stack {

private:

vector<T> elems; // elements

public:

void push(T const&); // push element

void pop(); // pop element

T top() const; // return top element

bool empty() const{ // return true if empty.

return elems.empty();

};

template <class T>

void Stack<T>::push (T const& elem)

// append copy of passed element

elems.push_back(elem);

template <class T>

15
void Stack<T>::pop ()

if (elems.empty()) {

throw out_of_range("Stack<>::pop(): empty stack");

16
// remove last element

elems.pop_back();

template <class T>

T Stack<T>::top () const

if (elems.empty()) {

throw out_of_range("Stack<>::top(): empty stack");

// return copy of last element

return elems.back();

int main()

try {

Stack<int> intStack; // stack of ints

Stack<string> stringStack; // stack of strings

// manipulate int stack

intStack.push(7);

17
cout << intStack.top() <<endl;

// manipulate string stack

stringStack.push("hello");

cout << stringStack.top() << std::endl;

18
stringStack.pop();

stringStack.pop();

catch (exception const& ex) {

cerr << "Exception: " << ex.what() <<endl;

return -1;

If we compile and run above code, this would produce the following result:

hello

Exception: Stack<>::pop(): empty stack

19
FILES IN C++

C++ provides the following classes to perform output and input of characters to/from files:

ofstream: Stream class to write on files


ifstream: Stream class to read from files
fstream: Stream class to both read and write from/to files.

These classes are derived directly or indirectly from the classes istream, and ostream. We
have already used objects whose types were these classes: cin is an object of class istream
and cout is an object of class ostream. Therfore, we have already been using classes that are
related to our file streams. And in fact, we can use our file streams the same way we are
already used to use cin and cout, with the only difference that we have to associate these
streams with physical files. Let's see an example:

// basic file operations


#include <iostream.h>
#include <fstream.h>

int main ()
{
ofstream myfile;
myfile.open ("example.txt");
myfile << "Writing this to a file.\n";
myfile.close();
return 0;
}

This code creates a file called example.txt and inserts a sentence into it in the same way we
are used to do with cout, but using the file stream myfile instead.

Open a file

The first operation generally performed on an object of one of these classes is to associate it
to a real file. This procedure is known as to open a file. An open file is represented within a
program by a stream object (an instantiation of one of these classes, in the previous example
this was myfile) and any input or output operation performed on this stream object will be
applied to the physical file associated to it.

In order to open a file with a stream object we use its member function open():

open (filename, mode);

Where filename is a null-terminated character sequence of type const char * (the same type
that string literals have) representing the name of the file to be opened, and mode is an
optional parameter with a combination of the following flags:

ios::in Open for input operations.


ios::out Open for output operations.
ios::binary Open in binary mode.
ios::ate Set the initial position at the end of the file.
If this flag is not set to any value, the initial position is the beginning of the file.
ios::app All output operations are performed at the end of the file, appending the content to
the current content of the file. This flag can only be used in streams open for output-only
operations.
ios::trunc If the file opened for output operations already existed before, its previous content
is deleted and replaced by the new one.

All these flags can be combined using the bitwise operator OR (|). For example, if we want to
open the file example.bin in binary mode to add data we could do it by the following call to
member function open():

ofstream myfile;
myfile.open ("example.bin", ios::out | ios::app | ios::binary);

Each one of the open() member functions of the classes ofstream, ifstream and fstream has a
default mode that is used if the file is opened without a second argument:

class default mode parameter


ofstream ios::out
ifstream ios::in
fstream ios::in | ios::out

For ifstream and ofstream classes, ios::in and ios::out are automatically and respectivelly
assumed, even if a mode that does not include them is passed as second argument to the
open() member function.

The default value is only applied if the function is called without specifying any value for the
mode parameter. If the function is called with any value in that parameter the default mode is
overridden, not combined.

File streams opened in binary mode, perform input and output operations independently of
any format considerations. Non-binary files are known as text files, and some translations
may occur due to formatting of some special characters (like newline and carriage return
characters)

Since the first task that is performed on a file stream object is generally to open a file, these
three classes include a constructor that automatically calls the open() member function and
has the exact same parameters as this member. Therefor, we could also have declared the
previous myfile object and conducted the same opening operation in our previous example by
writing:

ofstream myfile ("example.bin", ios::out | ios::app | ios::binary);

Combining object construction and stream opening in a single statement. Both forms to open
a file are valid and equivalent.
To check if a file stream was successful opening a file, you can do it by calling to member
is_open() with no arguments. This member function returns a bool value of true in the case
that indeed the stream object is associated with an open file, or false otherwise:

if (myfile.is_open()) { /* ok, proceed with output */ }

Closing a file
When we are finished with our input and output operations on a file we shall close it so that
its resources become available again. In order to do that we have to call the stream's member
function close(). This member function takes no parameters, and what it does is to flush the
associated buffers and close the file:
myfile.close();

Once this member function is called, the stream object can be used to open another file, and
the file is available again to be opened by other processes.

In case that an object is destructed while still associated with an open file, the destructor
automatically calls the member function close().

Text files
Text file streams are those where we do not include the ios::binary flag in their opening
mode. These files are designed to store text and thus all values that we input or output from/to
them can suffer some formatting transformations, which do not necessarily correspond to
their literal binary value.
Data output operations on text files are performed in the same way we operated with cout:

// writing on a text file


#include <iostream>
#include <fstream>
using namespace std;

int main () {
ofstream myfile ("example.txt");
if (myfile.is_open())
{
myfile << "This is a line.\n";
myfile << "This is another line.\n";
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
[file example.txt]
This is a line.
This is another line.

Data input from a file can also be performed in the same way that we did with cin:
// reading a text file
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main () {
string line;
ifstream myfile ("example.txt");
if (myfile.is_open())
{
while (! myfile.eof() )
{
getline (myfile,line);
cout << line << endl;
}
myfile.close();
}

else cout << "Unable to open file";

return 0;
}
This is a line.
This is another line.

This last example reads a text file and prints out its content on the screen. Notice how we
have used a new member function, called eof() that returns true in the case that the end of the
file has been reached. We have created a while loop that finishes when indeed myfile.eof()
becomes true (i.e., the end of the file has been reached).

Checking state flags


In addition to eof(), which checks if the end of file has been reached, other member functions
exist to check the state of a stream (all of them return a bool value):

bad()
Returns true if a reading or writing operation fails. For example in the case that we try to
write to a file that is not open for writing or if the device where we try to write has no space
left.
fail()
Returns true in the same cases as bad(), but also in the case that a format error happens, like
when an alphabetical character is extracted when we are trying to read an integer number.
eof()
Returns true if a file open for reading has reached the end.
good()
It is the most generic state flag: it returns false in the same cases in which calling any of the
previous functions would return true.
In order to reset the state flags checked by any of these member functions we have just seen
we can use the member function clear(), which takes no parameters.

get and put stream pointers


All i/o streams objects have, at least, one internal stream pointer:
ifstream, like istream, has a pointer known as the get pointer that points to the element to be
read in the next input operation.

ofstream, like ostream, has a pointer known as the put pointer that points to the location
where the next element has to be written.

Finally, fstream, inherits both, the get and the put pointers, from iostream (which is itself
derived from both istream and ostream).

These internal stream pointers that point to the reading or writing locations within a stream
can be manipulated using the following member functions:

tellg() and tellp()


These two member functions have no parameters and return a value of the member type
pos_type, which is an integer data type representing the current position of the get stream
pointer (in the case of tellg) or the put stream pointer (in the case of tellp).

seekg() and seekp()


These functions allow us to change the position of the get and put stream pointers. Both
functions are overloaded with two different prototypes. The first prototype is:
seekg ( position );
seekp ( position );

Using this prototype the stream pointer is changed to the absolute position position (counting
from the beginning of the file). The type for this parameter is the same as the one returned by
functions tellg and tellp: the member type pos_type, which is an integer value.

The other prototype for these functions is:

seekg ( offset, direction );


seekp ( offset, direction );

Using this prototype, the position of the get or put pointer is set to an offset value relative to
some specific point determined by the parameter direction. offset is of the member type
off_type, which is also an integer type. And direction is of type seekdir, which is an
enumerated type (enum) that determines the point from where offset is counted from, and that
can take any of the following values:

ios::beg offset counted from the beginning of the stream


ios::cur offset counted from the current position of the stream pointer
ios::end offset counted from the end of the stream

The following example uses the member functions we have just seen to obtain the size of a
file:

// obtaining file size


#include <iostream>
#include <fstream>
using namespace std;

int main () {
long begin,end;
ifstream myfile ("example.txt");
begin = myfile.tellg();
myfile.seekg (0, ios::end);
end = myfile.tellg();
myfile.close();
cout << "size is: " << (end-begin) << " bytes.\n";
return 0;
}
size is: 40 bytes.
Chapter:16 STL and Lambda

 Lambda Expression.
 Functions – STL
 Generic Programming

1
1 Introduction 3

2 Why use Lambda Expressions 3

3 Default Capture Modes 6


3.1 Default By-Reference Capture ................................................................... 6
3.2 Default By-Value Capture ........................................................................... 7
3.3 Summary ................................................................................................... 9

4 Moving Objects Into Closure 9

2
1 Introduction
Lambda expressions are an important feature in modern C++.
The goal of ”Lambda Expressions in C++14 and C++17
(part 1)” is to give a basic overview of lambda expressions
covering benefits and pitfalls when using them.
Since the vocabulary associated with lambdas can be confusing
let us take a look at a brief refresher from [Mey14]
• A lambda expression is just that: an expression. It‟s part of
the source code.
std::find_if(container.begin(), container.end(),
[](int val) { return 1 < val && val < 10; }
);

• The closure is the runtime object created by a lambda.


Depending on the capture mode, closures hold copies of or
references to the captured data.
• A closure class is a class from which a closure is instantiated.
Each lambda causes compilers to generate a unique closure
class. The state- ments inside a lambda become executable
instructions in the member functions of its closure class.

2 Why use Lambda Expressions


“Lambda expressions - lambdas - are a game changer in C++
programming. That‟s somewhat surprising because they bring no
new expressive power to the language” (Scott Meyers)
Looking at the quote above raises the question why to use lambda
expressions in modern C++.
One benefit of lambda expressions is that they can often improve
code read- ability. This is because they can be declared at the point
where they are used and are anonymous which can avoid redundant
names for one-off calls. Let us consider the following simple
example of removing multiples of five from a container.

3
bool multiple_of_5(int value){
return value % 5 == 0;
}

//...

void do_work() {
auto numbers = std::vector<int>();
//...

4
std::remove_if(
numbers.begin(), numbers.end(),
multiple_of_5
);
//...
}

Using the STL algorithm std::remove_if we have to specify a


predicate that returns true if an element should be removed from the
container. Note that there might be a considerable amount of code
between the definitions of multiple_of_5 and do_work making it
harder to follow the individual steps of a function while reading it.
The need to use named functions often results in a number of
trivial, one-off predicates cluttering a source file. These problems
can be avoided by using lambda expressions as shown below:
void do_work() {
auto numbers = std::vector<int>();
//...
std::remove_if(
numbers.begin(), numbers.end(),
[](int value){
return value % 5 == 0;
}
);
//...
}

An even bigger benefit of lambda expressions is that they


drastically simplify the creation of function objects. This allows to
quickly create for example
• more complex predicates and comparators for STL
algorithms (e.g. std::find_if or std::sort).
• custom deleters for smart pointers.
• predicates for condition variables in the threading API
Let us assume that instead of hard-coding the divisor in the
previous example we wanted to compute its value at runtime. The
traditional way to create predicates with additonal state is as
follows:
5
//Closure Class
class MultipleOf {
public:
MultipleOf(int divisor) : divisor(divisor) {}

bool operator()(const int value) {

6
return value % divisor == 0;
}
private:
int divisor;
};

void do_work() {
auto numbers = std::vector<int>();
//...
auto divisor = calc_divisor(...);
//Closure (Object)
auto multiple_of_divisor = MultipleOf(divisor);
std::remove_if(
numbers.begin(), numbers.end(),
multiple_of_divisor
);
//...
}

The idea is to create a class with an overloaded call operator


and data members containing the additional state. An
appropriately initialized instance of this class is then passed to
std::remove_if. Setting aside the previously mentioned problems
we can see that this approach creates a considerable amount of
boilerplate code. This can make it harder to understand the code and
easier to introduce errors making it harder to maintain the code.
Writing this boilerplate code may also discourage programmers
from using libraries like STL algorithm and instead resort to
shorter handwritten alternatives. This is undesirable as such
handwritten code is usually less tested, has worse performance and is
harder to understand than used standardized library functions.
With lambda expressions the example above can be expressed as follows:

7
void do_work() {
auto numbers = std::vector<int>();
//...
auto divisor = calc_divisor(...);
std::remove_if(
numbers.begin(), numbers.end(),
[divisor](const int value) {
return value % divisor == 0;
}
);
//...
}

8
3 Default Capture Modes
Since the addition of lambda expressions in C++11 there are two
default capture modes: by-reference and by-value. Capturing local
variables can lead to dan- gling references. Using the default by-
value capture mode gives the impression that a lambda expression
is self-contained although it might result in dangling pointers or
referenced variables. This section covers why default capture
modes should be not be used and offers solutions to avoid the
problems mentioned above.

3.1 Default By-Reference Capture


A by-reference capture of a local variable or a parameter in the
scope where lambda expression is defined causes the closure to
contain a reference to it. The default by-reference capture mode
instructs the compiler to find all not explicitly captured local
variables or parameters used in the lambda expression and capture
them by reference.
In the example below the local variable divisor is automatically
captured by reference. The lambda expression will return true if
value is dividable by divisor resulting in all multiples of divisor
being removed from numbers.
void do_work() {
auto numbers = std::vector<int>();
//...
auto divisor = calc_divisor(...);
std::remove_if(
numbers.begin(),
numbers.end(),[&](const int
value) {
return value % divisor == 0;
}
);
//...
}

The problem of by-reference capture is that reference stored in the


closure will dangle if the lifetime of the closure exceeds the lifetime of
the captured local variable variable or parameter. To illustrate this let
us assume that we found the lambda expression from above usefull
and copied it into a different function.
9
std::vector<std::function<bool(int)> filters;

void add_filter() {
//...
auto divisor = calc_divisor(...);

filters.emplace_back(

[&](const int value) {


return value % divisor == 0; //dangling ref.!
}
);
}

The closure of the lambda expression is added to the container of


filter func- tions called filters which is a global variable. Because the
lifetime of the clo- sure exceeds the lifetime of divisor (i.e. the scope
of the function add_filter) the reference to divisor will immediately
dangle and calling the filter function will result in undefined
behaviour. This mistake is easy to make (e.g. copying code) and
can be hard to find because it is easily overlooked especially in
more complex lambda expressions and a runtime error might occur
in a completely different part of the code. It is also important to
note that the compiler will typically give no warning about this
problem.
While there is (currently) no way to completely avoid dangling
references in lambda expressions we can reduce the likelihood by
explicitly capturing local variables and parameters.
[&divisor](int value) {
return value % divisor;
}

Doing so makes it more obvious that the lambda expression above


depends on the lifetime of divisor when reading the code and can
also act as a reminder to check for lifetime issues while writing the
code.

3.2 Default By-Value Capture


.
Default by-value capture is basically the same as default by-
reference capture except that the closure contains a copy of the
captured variable instead of a reference to it. This is usually used
when the lifetime of the closure exceeds the lifetime of the captured
10
variable and it avoids the problem of dangling references. The
problem of using the default by-value capture mode is that it
might still result in dangling pointers or referenced variables.
Let us consider the following code where the only difference to
the previous example is that we
want to capture the value of a data member inside a class member function.
class Widget {
public:
//...
void add_filter();
private:
int divisor;
}

void Widget::add_filter() {
filters.emplace_back(
[=](const int value) {
return value % divisor == 0; //this pointer
//might dangle
}
);
}

Although this might look like divisor is copied in reality the objects
this pointer is captured by-value. If the closure outlives the Widget
object which created it the this pointer will dangle. This is because
lambdas can only capture local variables and parameters from the
scope they are defined in. It is actually impossible to capture data
members directly. A solution to this problem is to copy the data
member to a local variable and capturing that by value. A better
void Widget::add_filter() {
filters.emplace_back(
[divisor = divisor](const int value) {
return value % divisor == 0;
}
);
}
way to solve this is to use the generalized lambda capture
introduced in C++14 as it avoids the definition of an otherwise
unused local variable.

This feature is called init capture and makes it possible to


specify the name of a data member in the closure class of the
generated lambda and an expression initialize it (
[name=expression](...){...}). In the example above the second
11
divisor is an expression evquivalent to this->divisor and is assigned to
the closures data member called divisor.
Another problem with default by-value capture is that it
misleadingly sug- gests that a lambda expression is self-contained

void add_filter(){
static int divisor = 5;
filters.emplace_back(
[=](const int value) { //this captures nothing
return value % divisor == 0; //divisor
//directly refers to static variable.
}
);
++divisor;
}
when a function has a static local variable.

12
Instead of capturing the value of divisor the standard states that the
lambda expression directly refers to the static variable which means that
the filter function will return multiples of six or whatever the current
value of the static variable is when the filter function is called. A
solution to this would be again to use the generalized lambda capture
syntax.

3.3 Summary
Avoid default capture modes because:
• Default by-reference capture can lead to dangling references.
• Default by-value capture
– is susceptible to dangling pointers (especially this).
– misleadingly suggests that lambdas are self-contained (static vari-
ables).

4 Moving Objects Into Closure


Sometimes neither by-reference nor by-value capture is what we want.
This includes objects that are expensive to copy (e.g. std::vector or
move-only like for instance std::unique_ptr or std::future. In
C++11 there was no way to move an object directly into a closure.
This behaviour could only be emulated with a handwritten class or using

void add_filter(){
//...
auto numbers =
produce_many_numbers(...);
filters.emplace_back(
[numbers=std::move(numbers)](const int value) {
//...
}
);
}

void add_filter(){
//...
filters.emplace_back(
[numbers=std::make_unique<Gadget>()]
(const int value) {
//...
}
);
std::bind.
} Using the generalized lambda capture this can be easily
achieved
Introduction to STL: Standard Template Library
STL is an acronym for standard template library. It is a set of C++ template classes that
provide generic classes and function that can be used to implement data structures and
algorithms. STL is mainly composed of:

1. Algorithms

2. Containers

3. Iterators

STL provides numerous containers and algorithms which are very useful in completive
programming, for example you can very easily define a linked list in a single statement by
using list container of container library in STL, saving your time and effort.

STL is a generic library, i.e a same container or algorithm can be operated on any data types,
you don‟t have to define the same algorithm for different type of elements.

For example, sort algorithm will sort the elements in the given range irrespective of their data
type , we don‟t have to implement different sort algorithm for different datatypes.
C++: Algorithms in STL

STL provide number of algorithms that can be used of any container, irrespective of their type.
Algorithms library contains built in functions that performs complex algorithms on the data
structures.

For example: one can reverse a range with reverse() function, sort a range with sort() function,
search in a range with binary_search() and so on.

Algorithm library provides abstraction, i.e you don't necessarily need to know how the the
algorithm works.

C++: Containers in STL

Container library in STL provide containers that are used to create data structures like
arrays, linked list, trees etc.

These container are generic, they can hold elements of any data types, for
example: vector can be used for creating dynamic arrays of char, integer, float and other types.

C++: Iterators in STL

Iterators in STL are used to point to the containers. Iterators actually acts as a bridge
between containers and algorithms.

For example: sort () algorithm have two parameters, starting iterator and ending
iterator, now sort () compare the elements pointed by each of these iterators and arrange them
in sorted order, thus it does not matter what is the type of the container and same sort() can be
used on different types of containers.

Use and Application of STL

STL being generic library provide containers and algorithms which can be used to store
and manipulate different types of data thus it saves us from defining these data structures and
algorithms from the scratch. Because of STL, now we do not have to define our sort function
every time we make a new program or define same function twice for the different data types,
instead we can just use the generic container and algorithms in STL.

This saves a lot of time, code and effort during programming, thus STL is heavily used
in the competitive programming, plus it is reliable and fast.
What are Containers in STL?

Containers Library in STL gives us the Containers, which in simplest words, can be
described as the objects used to contain data or rather collection of object. Containers help us
to implement and replicate simple and complex data structures very easily like arrays, list,
trees, associative arrays and many more.

The containers are implemented as generic class templates, means that a container can
be used to hold different kind of objects and they are dynamic in nature!

Following are some common containers :

 vector : replicates arrays

 queue : replicates queues

 stack : replicates stack

 priority_queue : replicates heaps

 list : replicates linked list

 set : replicates trees

 map : associative arrays

Classification of Containers in STL

Containers are classified into four categories :

 Sequence containers : Used to implement data structures that are sequential in nature
like arrays(array) and linked list(list).

 Associative containers : Used to implement sorted data structures such as map, set etc.

 Unordered associative containers : Used to implement unsorted data structures.

 Containers adaptors : Used to provide different interface to the sequence containers.


Using Container Library in STL

Below is an example of implementing linked list, first by using structures and then by
list containers.

#include <iostream>

struct node

int data;

struct node * next;

int main ()

struct node *list1 = NULL;

The above program is only creating a list node, no insertion and deletion functions are
defined, to do that, you will have to write more line of code.

Now lets see how using Container Library simplifies it. When we use list containers to
implement linked list we just have to include the list header file and use list constructor to
initialize the list.

#include <iostream>

#include <list>
int main ()

list<int> list1;

And that's it! we have a list, and not just that, the containers library also give all the
different methods which can be used to perform different operations on list such as insertion,
deletion, traversal etc.

Thus, you can see that it is incredibly easy to implement data structures by using
Container library.

PAIR Template in STL

Although Pair and Tuple are not actually the part of container library but we'll still
discuss them as they are very commonly required in programming competitions and they make
certain things very easy to implement.

SYNTAX of pair is:

pair<T1,T2> pair1, pair2 ;


The above code creates two pairs, namely pair1 and pair2, both having first object of
type T1 and second object of type T2.

Now T1 will be referred as first and T2 will be referred as second member of pair1 and
pair2.

Here are some function for pair template :


Operator = : assign values to a pair.
swap: swaps the contents of the pair.
make pair (): create and returns a pair having objects defined by parameter list.
Operators (==, =, > , < , <= , >= ) : lexicographically compares two pairs.
Program demonstrating PAIR Template
#include <iostream>
using namespace std;
int main ()
{
pair<int,int> pair1, pair3; //creats pair of integers
pair<int,string> pair2; // creates pair of an integer an a string

pair1 = make_pair(1, 2); // insert 1 and 2 to the pair1


pair2 = make_pair(1, "Studytonight") // insert 1 and "Studytonight" in pair2
pair3 = make_pair(2, 4)
cout<< pair1.first << endl; // prints 1, 1 being 1st element of pair1
cout<< pair2.second << endl; // prints Studytonight

if(pair1 == pair3)
cout<< "Pairs are equal" << endl;
else
cout<< "Pairs are not equal" << endl;
}

TUPLE in STL
tuple and pair are very similar in their structure. Just like in pair we can pair two
heterogeneous object, in tuple we can pair three heterogeneous objects.

SYNTAX of a tuple is:

// creates tuple of three object of type T1, T2 and T3

tuple<T1, T2, T3> tuple1;


Tuple Template: Some Commonly used Functions

Similar to pair, tuple template has its own member and non-member functions, few of which
are listed below :

 A Constructor to construct a new tuple

 Operator = : to assign value to a tuple

 swap : to swap value of two tuples

 make_tuple() : creates and return a tuple having elements described by the parameter
list.

 Operators( == , != , > , < , <= , >= ) : lexicographically compares two pairs.

 Tuple_element : returns the type of tuple element

 Tie : Tie values of a tuple to its refrences.

Program demonstrating Tuple template

#include <iostream>

int main ()

tuple<int, int, int> tuple1; //creates tuple of integers


tuple<int, string, string> tuple2; // creates pair of an integer an 2 string

tuple1 = make_tuple(1,2,3); // insert 1, 2 and 3 to the tuple1

tuple2 = make_pair(1,"Studytonight", "Loves You");

/* insert 1, "Studytonight" and "Loves You" in tuple2 */

int id;

string first_name, last_name;

tie(id,first_name,last_name) = tuple2;

/* ties id, first_name, last_name to

first, second and third element of tuple2 */

cout << id <<" "<< first_name <<" "<< last_name;

/* prints 1 Studytonight Loves You */

return 0;

}
ARRAY Container in STL
Arrays, as we all know, are collection of homogenous objects. array container in STL
provides us the implementation of static array, though it is rarely used in competitive
programming as its static in nature but we'll still discuss array container cause it provides
some member functions and non-member functions which gives it an edge over the array
defined classically like, int array_name[array_size].

SYNTAX of array container:

array<object_type, array_size> array_name;

The above code creates an empty array of object_type with maximum size
of array_size. However, if you want to create an array with elements in it, you can do so by
simply using the = operator, here is an example :

#include <vector>

int main()

array<int, 4> odd_numbers = { 2, 4, 6, 8 };

The above statement will create an array with 2,4,6,8 as data in the array. Note that
initialization with {} brackets is only possible in c++ 17.

Member Functions of Array Template

Following are the important and most used member functions of array template.

At() function

This method returns value in the array at the given range. If the given range is greater than
the array size, out_of_range exception is thrown. Here is a code snippet explaining the use of
this operator :
#include <iostream>

#include <array>

using namespace std;

int main ()

array<int,10> array1 = {1,2,3,4,5,6,7,8,9};

cout << array1.at(2) // prints 3

cout << array1.at(4) // prints 5

[ ] Operator

The use of operator [ ] is same as it was for normal arrays. It returns the value at the given
position in the array. Example : In the above code, statement cout << array1[5]; would print 6
on console as 6 has index 5 in array1.

front() function

This method returns the first element in the array.

back() function

This method returns the last element in the array. The point to note here is that if the array is
not completely filled, back() will return the rightmost element in the array.
fill() function

This method assigns the given value to every element of the array, example :

#include <array>

int main()

array<int,8> myarray;

myarray.fill(1);

This will fill the array myarray with value as 1, at all of its 8 available positions.

Swap() function

This method swaps the content of two arrays of same type and same size. It swaps index
wise, thus element of index i of first array will be swapped with the element of index i of the
second array, and if swapping any of the two elements thows an execption, swap() throws
exception. Below is an example to demonstrate its usage :

#include <array>

int main()

array<int,8> a = {1,2,3,4,5,6,7,8};

array<int,8> b = {8,7,6,5,4,3,2,1};
a.swap(b) // swaps array a and b

cout << "a is : ";

for(int i=0; i < 8; i++) {

cout << a[i] <<" ";

cout << endl;

cout << "b is : ";

for(int i=0; i < 8; i++) {

cout << a[i] <<" ";

/* ouput will be

a is : 8 7 6 5 4 3 2 1

b is : 1 2 3 4 5 6 7 8 */

operators ( == , != , > , < , >= , <= )

All these operators can be used to lexicographically compare values of two arrays.

Empty() function

This method can be used to check whether the array is empty or not.

Syntax: array_name.empty(), returns true if array is empty else return false.


Size() function

This method returns the number of element present in the array.

max_size() function

This method returns the maximum size of the array.

Begin() function

This method returns the iterator pointing to the first element of the array. Iterators are just
like pointers and we‟ll discuss them later in the lessons, for now you can just think of an
iterator like a pointer to the array.

End() function

This method returns an iterator pointing to an element next to the last element in the array,
for example the above array has 4 elements and the end() call will return the iterator pointing
to the 4th index of the array.

VECTOR Container in STL


An array works fine when we have to implement sequential data structures like
arrays, except it is static, i.e. we have to define its maximum size during its initialization and
it cannot contain elements greater than its maximum size. Now suppose, if during the
program execution we have to store elements more than its size, or if we are reading input
stream of elements and we do not know the upper bound of the number of elements, there are
high chances of occurrence of index_out_bound exception or unwanted termination of the
program.

We can do one thing, initialize the array with maximum size allowed by the complier,
i.e. 10^6 elements per array, but that is highly space consuming approach and there is a
wastage of space if number of elements to be entered are way too less, thus this approach is
never used in programming.
Solution of the above problem is dynamic arrays! They have dynamic size, i.e. their size can
change during runtime. Container library provides vectors to replicate dynamic arrays.

SYNTAX for creating a vector is: vector< object_type > vector_name;

For example:

#include <vector>

int main()

std::vector<int> my_vector;

Vector being a dynamic array, doesn't needs size during declaration, hence the above
code will create a blank vector. There are many ways to initialize a vector like,

#include <vector>

int main()

std::vector<string> v {"Pankaj" ,"The" ,"Java" ,"Coder"};

}
Note that this type of initialization works only in C++ 11 and above. You can also
initialize the vector based on the range of other vectors, like :

#include <vector>

int main()

std::vector<string> v(v1.begin(), v1.end());

The above code initialize the vector by elements pointed by iterators returned by
v1.begin() and v2.end(), begin() and end() are the same function we have studied with array,
they work same with vectors.

You can also initialize a vector with one element a certain number of times, like :

#include <vector>

int main()

std::vector<string> v(4 , "test");

}
These are me of the ways using which you can initialize your vector, but remember,
initializing your vector using another vector or by using elements directly does not limit its
size, its size will always be dynamic, and more elements can be inserted into the vector,
whenever required.

Member Functions of Vector

Following are some of the most commonly used functions for vector container in STL:

push_back function

push_back() is used for inserting an element at the end of the vector. If the type of object
passed as parameter in the push_back() is not same as that of the vector or is not
interconvertible an exception is thrown.

The following illustration will show how push_back() works:


#include <iostream>

#include <vector>

using namespace std;

int main()

vector<int> v;

v.push_back(1); //insert 1 at the back of v

v.push_back(2); //insert 2 at the back of v

v.push_back(4); //insert 3 at the back of v

for(vector<int>::iterator i = v.begin(); i != v.end(); i++)

cout << *i <<" "; // for printing the vector

124

insert function

insert(itr, element) method inserts the element in vector before the position pointed by iterator
itr.
The following illustration will show how insert works :

insert function can be overloaded by third argument, count as well. This count parameter
defines how many times the element is to be inserted before the pointed position.

This method can also be used to insert elements from any other vector in given range,
specified by two iterators, defining starting and ending point of the range.

v.insert(i, v2.begin(), v2.end());

Above code will insert the elements from v2.begin() to v2.end() before index pointed by i.
pop_back function

pop_back() is used to remove the last element from the vector. It reduces the size of the
vector by one.

Below is an example:

#include <iostream>

#include <vector>

using namespace std;

int main()

vector<int> v1 {10,20,30,40};

v1.pop_back();

vector<int>::iterator it;
for(it = v.begin(); it != v.end(); it++)

cout << *it <<" "; // for printing the vector

10 20 30

erase function

erase(itr_pos) removes the element pointed by the iterator itr_pos. erase method can also be
overloaded with an extra iterator specifying the end point of the range to be removed,
i.e erase(itr_start, itr_end).

The following code will illustrate erase:

#include <iostream>

#include <vector>

using namespace std;

int main()

vecto<int>v1 {10,20,30,40};

vector<int>iterator:: it = v.begin();
v.erase(it); //removes first element from the vector

v.erase(v1.begin(), v1.end() - 2 )

/*removes all the elements except last two */

for(it = v.begin(); it != v.end(); it++)

cout << *it <<" "; // for printing the vector

30 40

resize function

resize(size_type n, value_type val) method resizes the vector to n elements. If the current size
of the vector is greater than n then the trailing elements are removed from the vector and if
the current size is smaller than n than extra val elements are inserted at the back of the vector.

For example, If the size of the vector is 4 right now, with elements {10, 20, 30, 40} and we
use resize method to resize it to size 5. Then by default a fifth element with value 0 will be
inserted in the vector. We can specify the data to not be zero, by explicitly mentioning it as
the val while calling the resize method.

swap function

This method interchanges value of two vectors.

If we have two vectors v1 and v2 and we want to swap the elements inside them, you just
need to call v1.swap(v2), this will swap the values of the two vectors.
clear function

This method clears the whole vector, removes all the elements from the vector but do not
delete the vector.

SYNTAX: clear()

For a vector v, v.clear() will clear it, but not delete it.

size function

This method returns the size of the vector.

empty function

This method returns true if the vector is empty else returns false.

capacity function

This method returns the number of elements that can be inserted in the vector based on the
memory allocated to the vector.

at function

This method works same in case of vector as it works for array. vector_name.at(i) returns the
element at ith index in the vector vector_name.

front and back functions

vector_name.front() retuns the element at the front of the vector (i.e. leftmost element).
While vector_name.back() returns the element at the back of the vector (i.e. rightmost
element).
LIST Container in STL
Array and Vector are contiguous containers, i.e they store their dataon continuous memory,
thus the insert operation at the middle of vector/array is very costly (in terms of number of
operaton and process time) because we have to shift all the elements, linked list overcome
this problem. Linked list can be implemented by using the list container.

Syntax for creating a new linked list using list template is:

#include <iostream>

#include <list>

int main()

std::list<int> l;

/* Creates a new empty linked list l */

Similar to vector and array, lists can also be intialised withparameters,

#include <iostream>

#include <list>

using namespace std;


int main()

std::list<int> l{1,2,3};

/* Creates a new linked list l */

Here are some more ways by which we can initialize our list:

#include <iostream>

#include <list>

int main()

list<int> myList{1,2,3};

/* creates list with 1,2,3 in it */


list<int> myNewList = 1;

/* create list myNewList of integer

and copies value of 1 into it*/

Member Functions of List Container

insert function

This method, as the name suggests, inserts an element at specificposition, in a list. There
are 3 variations of insert(), they are as follows :

 insert(iterator, element) : inserts element in the list before theposition pointed by


the iterator.

 insert(iterator, count, element) : inserts element in the list beforethe position


pointed by the iterator, count number of times.

 insert(iterator, start_iterator, end_iterator): insert the elementpointed by


start_iterator to the element pointed
by end_iterator before the position pointed by iterator

#include <iostream>

#include <list>
using namespace std;

int main()

list<int> l = {1,2,3,4,5};

list<int>::iterator it = l.begin();

l.insert (it+1, 100); // insert 100 before


2 position

/* now the list is 1 100 2 3 4 5 */

list<int> new_l = {10,20,30,40}; // new list

new_l.insert (new_l.begin(), l.begin(),l.end());

/*

insert elements from beginning of list lto end of list l

before 1 position in list new_l */

/* now the list new_l is 1 100 2 3 4 5 10 20


30 40 */
l.insert(l.begin(), 5, 10); // insert 10
before beginning 5 times

/* now l is 10 10 10 10 10 1 100 2 3 4 5 */

return 0;

push_back and push_front functions

push_back(element) method is used to push elements into a list fromthe back.

push_front(element) method is used to push elements into a list fromthe front.


#include <iostream>

#include <list>

using namespace std;

int main()

list<int> l{1,2,3,4,5};

l.push_back(6);

l.push_back(7);

/* now the list becomes 1,2,3,4,5,6,7 */

l.push_front(8);

l.push_front(9);
/* now the list becomes 9,8,1,2,3,4,5,6,7 */

pop_back and pop_front functions

pop_front() removes first element from the start of the list. While pop_back()
removes first element from the end of the list.

#include <iostream>

#include <list>

using namespace std;

int main()

list<int> l{1,2,3,4,5};

l.pop_back()();

/* now the list becomes 1,2,3,4 */

l.pop_front()();
/* now the list becomes 2,3,4 */

empty function

This method returns true if the list is empty else returns false.

size function

This method can be used to find the number of elements present inthe list.

front and back function

front() is used to get the first element of the list from the start
while back() is used to get the first element of the list from the back.

swap function

Swaps two list, if there is exception thrown while swapping anyelement, swap()
throws exception. Both lists which are to be swapped must be of the same type, i.e you
can‟t swap list of aninteger with list of strings.

reverse function

This method can be used to reverse a list completely.

#include <iostream>

#include <list>
using namespace std;

int main()

list<int> l{1,2,3,4,5};

l.reverse();

/* now the list becomes 5,4,3,2,1 */

sort function

sort() method sorts the given list. It does not create new sorted list but changes the position
of elements within an existing list to sortit. This method has two variations :

 sort() : sorts the elements of the list in ascending order, theelement of the list
should by numeric for this function.

 sort(compare_function) : This type of sort() is used when we have to alter the method
of sorting. Its very helpful for the elementsthat are not numeric. We can define how
we want to sort the list elements in compare_funtion. For example, list of strings can
be sorted by the length of the string, it can also be used for sorting in descending
order.

#include <iostream>
#include <list>

using namespace std;

bool compare_function( string& s1 , string& s2 )

return ( s1.length() > s2.length() );

int main()

list<int> list1 = {2,4,5,6,1,3};

list<string> list2 = {"h", "hhh", "hh"};

list1.sort();

/* list1 is now 1 2 3 4 5 6 */

list2.sort(compare_function);

/* list2 is now h hh hhh */

}
splice function

splice() method transfers the elements from one list to another.There are three versions
of splice :

 splice(iterator, list_name) : Transfers complete list list_name atposition pointed


by the iterator.

 splice(iterator, list_name, iterator_pos) : Transfer elements pointedby iterator_pos


from list_name at position pointed
by iterator.

 splice(iterator, list_name, itr_start, itr_end) : Transfer range specifiedby itr_start


and itr_end from list_name at position pointed by iterator.

#include <iostream>

#include <list>

using namespace std;

int main ()

list<int> list1 = {1,2,3,4};

list<int> list2 = {5,6,7,8};

list<int>::iterator it;
it = list1.begin();

++it; //pointing to second position

list1.splice(it, list2);

/* transfer all elements of list2 at position


2 in list1 */

/* now list1 is 1 5 6 7 8 2 3 4 and list2 is


empty */

list2.splice(list2.begin(), list1, it);

/* transfer element pointed by it in list1 to


the beginning of list2 */

/* list2 is now 5 and list1 is 1 6 7 8 2 3 4*/

return 0;

merge function
Merges two sorted list. It is mandatory that both the list should besorted first. merge()
merges the two list such that each element is placed at its proper position in the resulting
list. Syntax for merge is list1.merge(list2).

The list that is passed as parameter does not get deleted and thelist which calls the
merge() becomes the merged list

#include <iostream>

#include <list>

using namespace std;

int main ()

list<int> list1 = {1,3,5,7,9};

list<int> list2 = {2,4,6,8,10};

/* both the lists are sorted. In case they are


not ,

first they should be sorted by sort function()


*/

list1.merge(list2);
/* list list1 is now 1,2,3,4,5,6,7,8,9,10 */

cout << list1.size() << endl; // prints 10

Lexicographically comparing Lists

Since lists are collection of elements, thus they do not have a standard value of their own. Thus
in order to compare list or vectorswe compare their elements in their lexicographical order.

For example, let list1 = { 1 , 2 , 3} and list2 = { 1 , 3 , 2 }, now if we want to check if the
list1 is greater than list2 or not, we just check the element of each list in the order they
appear in the lists. Since 1in list1 is equal to 1 in list2, we proceed further, now 2 in list1 is
smaller then 3 in list2, thus list2 is lexicographically greater than list1.

Operators == , > , < , <= , >= can be used to compare listslexicographically.


MAP Container in STL
Maps are used to replicate associative arrays. Maps contain sorted key-value pair, in
which each key is unique and cannot bechanged, and it can be inserted or deleted but
cannot be altered.Value associated with keys can be altered. We can search, removeand
insert in a map within O(n) time complexity.

For example: A map of students where roll number is the keyand name is the value
can be represented graphically as :

Notice that keys are arranged in ascending order, its because maps always arrange its keys in
sorted order. In case the keys are of stringtype, they are sorted lexicographically.

Creating a Map in C++ STL

Maps can easily be created using the following statement :

map<key_type , value_type> map_name;


This will create a map with key of type Key_type and value of
type value_type. One thing which is to remembered is that key of amap and corresponding
values are always inserted as a pair, you cannot insert only key or just a value in a map.

Here is a program that will illustrate creating a map in differentways:

#include <iostream>

#include <map>

using namespace std;

int main ()

map<int,int> m{ {1,2} , {2,3} , {3,4} };

/* creates a map m with keys 1,2,3 and

their corresponding values 2,3,4 */

map<string,int> map1;

/* creates a map with keys of type character


and

values of type integer */


map1["abc"]=100; // inserts key = "abc"
with value = 100

map1["b"]=200; // inserts key = "b" with


value = 200

map1["c"]=300; // inserts key = "c" with


value = 300

map1["def"]=400; // inserts key = "def"


with value = 400

map<char,int> map2 (map1.begin(), map1.end());

/* creates a map map2 which have entries


copied

from map1.begin() to map1.end() */

map<char,int> map3 (m);

/* creates map map3 which is a of map m */

Member Functions of Map in C++ STL


Following are some of the commonly used function of Mapcontainer in STL:

at and [ ]

Both at and [ ] are used for accessing the elements in the map. Theonly difference between
them is that at throws an exception if the accessed key is not present in the map, on the
other hand operator [ ] inserts the key in the map if the key is not present already in the
map.

#include <iostream>

#include <map>

using namespace std;

int main ()

map<int,string> m{ {1,”nikhilesh”} ,
{2,”shrikant”} , {3,”ashish”} };

cout << m.at(1) ; // prints value associated


with key 1 ,i.e nikhilesh

cout << m.at(2) ; // prints value associated


with key 2 ,i.e shrikant
/* note that the parameters in the above at()are the keys not the index */

cout << m[3] ; // prints value associated withkey 3 , i.e ashish

m.at(1) = "vikas"; // changes the valueassociated with


key 1 to vikas

m[2] = "navneet"; // changes the valueassociated with


key 2 to navneet

m[4] = "doodrah";

/* since there is no key with value 4 in the


map,

it insert a key-value pair in map withkey=4 and value = doodrah */

m.at(5) = "umeshwa";

/* since there is no key with value 5 in themap ,


it throws an exception */

empty, size and max_size

empty() returns boolean true if the map is empty, else it returns Boolean false. size() returns
number of entries in the map, an entryconsist of a key and a value. max_size() returns the
upper bound ofthe entries that a map can contain (maximum possible entries) based on the
memory allocated to the map.

insert and insert_or_assign

insert() is used to insert entries in the map. Since keys are unique in a map, it first checks
that whether the given key is already present inthe map or not, if it is present the entry is not
inserted in the map and the iterator to the existing key is returned otherwise new entry is
inserted in the map.

There are two variations of insert():

 insert(pair) : In this variation, a pair of key and value is insertedin the map. The
inserted pair is always inserted at the appropriate position as keys are arranged in
sorted order.

 insert(start_itr , end_itr): This variation inserts the entries in rangedefined by


start_itr and end_itr of another map.

The insert_or_assing() works exactly as insert() except that if the givenkey is already present in
the map then its value is modified.

#include <iostream>

#include <map>
using namespace std;

int main ()

map<int,int> m{{1,2} , {2,3} , {3,4} };

m.insert( pair<int,int> (4,5));

/* inserts a new entry of key = 4 and value =


5 in map m */

/* make_pair() can also be used for creating apair */

m.insert( make_pair(5, 6));

/* inserts a new entry of key = 5 and value =6 */

map::iterator i , j;

i = m.find(2); // points to entry havingkey =2


j = m.find(5); // points to entry having
key =5

map<int,int> new_m;

new_m.insert(i,j);

/* insert all the entries which are pointed

by iterator i to iterator j*/

m.insert( make_pair(3,6));

// do not insert the pair as map m already


contain key = 3 */

m.insert_or_assign( make_pair(3,6)); //
assign value = 6 to key =3

erase and clear

erase() removes the entry from the map pointed by the iterator (which is passed as
parameter), however if we want to remove all the elements from the map, we can use clear(),
it clears the map andsets its size to 0.
There are two variations of erase :

 erase(iterator_itr) : This removes entry from the map pointed byiterator iterator_itr,
reducing the size of map by 1.

 erase(start_iterator, end_iterator) : It removes the elements inrange specified


by the start_iterator and end_iterator.

begin, end and find

begin, end and find returns an iterator. begin() returns the iterator tothe starting entry of the
map, end() returns the iterator next to the last entry in the map and find() returns the iterator
to the entry having key equal to given key (passed as parameter).
STACK Container in C++ STL
The stack container is used to replicate stacks in c++, insertion anddeletion is always
performed at the top of the stack.

To know more about the Stack data Structure, visit: STACK DataStructure

Here is the syntax of defining a stack in stl :

stack<object_type> stack_name;

The above statement will create a stack named stack_name of typeobject_type.

Member Functions of Stack Container

Following are some of the most commonly used functions of Stackcontainer in STL:

push function

push() is used to insert the element in the stack, the elements areinserted at the top of the
stack.
#include <iostream>

#include <stack>

using namespace std;

int main ()

stack<int> s; // creates an empty stack of


integer s
s.push(2); // pushes 2 in the stack , now
top =2

s.push(3); // pushes 3 in the stack , now


top =3

pop function

This method is used to removes single element from the stack. It reduces the size of the
stack by 1. The element removed is alwaysthe topmost element of the stack (most recently
added element) .The pop() method does not return anything.

top function
This method returns the topmost element of the stack. Note thatthis method returns the
element, not removes it, unlike pop().

SYNTAX: top()

size and empty functions

size() returns the number of elements present in the stack, whereas empty() checks if the
stack is empty or not. empty returnstrue if the stack is empty else false is returned.

swap function

This method swaps the elements of the two stacks.

#include <iostream>

#include <stack>

using namespace std;

int main ()

stack<int> s;

// pushing elements into stack

s.push(2);

s.push(3);
s.push(4);

cout << s.top(); // prints 4, as 4 is the


topmost element

cout << s.size(); // prints 3, as there are 3


elements in

QUEUE Container in STL


The queue container is used to replicate queue in C++, insertion always takes place at
the back of the queue and deletion isalways performed at the front of the queue.

Here is the syntax for defining a queue:

queue< object_type > queue_name;

The above statement will create a queue named queue_name


of type object_type.

Member Functions of Queue Container

Following are some of the commonly used functions of QueueContainer in STL:

push function

push() is used to insert the element in the queue. The element isinserted at the back or rear of
the queue.
#include <iostream>

#include <queue>

using namespace std;

int main ()

queue <int> q; // creates an empty queue of


integer q

q.push>(2); // pushes 2 in the queue , now


front = back = 2
q.push(3); // pushes 3 in the queue , now
front = 2 , and back = 3

pop function

This method removes single element from the front of the queue and therefore reduces its
size by 1. The element removed is the element that was entered first. the pop() does not
return anything.

#include <iostream>

#include <queue>

using namespace std;

int main ()

queue <int> q; // creates an empty queue of


integer q

q.push>(2); // pushes 2 in the queue , now


front = back = 2
q.push(3); // pushes 3 in the queue , now
front = 2 , and back = 3

q.pop() ; // removes 2 from the stack , front


= 3

front and back functions

front() returns the front element of the queue whereas back() returnsthe element at the back of
the queue. Note that both returns the element, not removes it, unlike pop().

size and empty functions

size() returns the number of elements present in the queue, whereas empty() checks if the
queue is empty or not. empty returnstrue if the queue is empty else false is returned.

Swap function

Method swap() Swaps the elements of the two queue.


PRIORITY QUEUE Container in C++ STL
priority_queue is just like a normal queue except the element removed from the queue is
always the greatest among all the elements in the queue, thus this container is usually used
to replicate Max Heap in C++. Elements can be inserted at any orderand it have O(log(n))
time complexity for insertion.

Following is the syntax for creating a priority queue:

priority_queue<int> pq;

Member Function of Priority Queue

Following are some of the commonly used functions of PriorityQueue Container in


STL:

push function

This method inserts an element in the priority_queue. The insertionof the elements have time
complexity of logarithmic time.

#include <iostream>>

#include <queue>

using namespace std;

int main ()
{

priority_queue<int> pq1;

pq1.push(30); // inserts 30 to pq1 , now top


= 30

pq1.push(40); // inserts 40 to pq1 , now top


= 40 ( maxinmum element)

pq1.push(90); // inserts 90 to pq1 , now top


= 90

pq1.push(60); // inserts 60 to pq1 , top


still is 90

return 0;

pop function

This method removes the topmost element from the priority_queue(greatest element)
,reducing the size of the priority queue by 1.

#include <iostream>>

#include <queue>

using namespace std;


int main ()

priority_queue<int> pq1;

pq1.push(30); // inserts 30 to pq1 , now top


= 30

pq1.push(40); // inserts 40 to pq1 , now top


= 40 ( maxinmum element)

pq1.push(90); // inserts 90 to pq1 , now top


= 90

pq1.push(60); // inserts 60 to pq1 , topstill is 90

pq1.pop(); // removes 90 ( greatest elementin the queue

return 0;

}
top function

This method returns the element at the top of the priority_queuewhich is the greatest element
present in the queue.

empty and size functions

size() returns the number of element present in the priority _queue, whereas empty() returns
Boolean true if the priority_queue is emptyelse Boolean false is returned.

swap function

This method swaps the elements of two priority_queue.

DEQUE Container in C++ STL


Deque is a shorthand for doubly ended queue. Deque allows fast insertion and deletion at
both ends of the queue. Although we can also use vector container for the insertion and
deletion at both of itsends, but insertion and deletion at the front of the array is costlier than at
the back, in case of deque but deque are more complex internally.

Syntax for creating a Deque is:

deque< object_type > deque_name;

Member Functions of Deque


Following are some of the commonly used functions of DequeContainer in STL:

push_back, push_front and insert functions

push_back(element e) inserts an element e at the back of the


deque, push_front(element e) inserts the element e at the front of thedeque.

insert() method has three variations :

 insert(iterator i, element e) : Inserts element e at the positionpointed by


iterator i in the deque.

 insert(iterator i, int count, element e) : Inserts


element e, count number of times from the position pointedby iterator i.

 insert(iterator i, iterator first, iterator last) : Inserts the element inthe range
[first,last] at the position pointed by iterator i in deque.

#include <iostream>

#include <deque>

#include <vector>

using namespace std;

int main ()

{
int a[] = { 1,5,8,9,3 };

deque<int> dq(a, a+5);

/* creates s deque with elements 1,5,8,9,3 */

dq.push_back(10);

/* now dq is : 1,5,8,9,3,10 */

dq.push_front(20);

/* now dq is : 20,1,5,8,9,3,10 */

deque<int>::iterator i;

i=dq.begin()+2;

/* i points to 3rd element in dq */

dq.insert(i,15);

/* now dq 20,1,15,5,8,9,3,10 */
int a[]={7,7,7,7};

d1.insert(dq.begin() , a , a+4 );

/* now dq is 7,7,7,7,20,1,15,5,8,9,3,10 */

pop_back and pop_front functions

pop_back() removes an element from the back of the deque whereas pop_front removes an
element from the front of the deque,both decreasing the size of the deque by one.

#include <iostream>

#include <deque>

#include <vector>

using namespace std;

int main ()

int a[] = { 1,5,8,9,3,5,6,4 };


deque<int> dq(a,a+8);

/* creates s deque with elements


1,5,8,9,3,5,6,4 */

dq.pop_back();

/* removes an element from the back */

/* now the deque dq is : 1,5,8,9,3,5,6 */

dq.pop_front();

/* now dq is : 1,5,8,9,3,5,6 */

empty, size and max_size functions

empty() returns Boolean true if the deque is empty, else Boolean false is returned. size()
returns the number of elements present inthe deque and max_size() returns the number of
element the givendeque can hold.

swap function

This method can be used to swap elements of two deques.


Overview of Iterators in C++ STL
As we have discussed earlier, Iterators are used to point to the containers in STL, because of
iterators it is possible for an algorithmto manipulate different types of data
structures/Containers.

Algorithms in STL don‟t work on containers, instead they work on iterators, they manipulate
the data pointed by the iterators. Thus it doesn‟'t matter what is the type of the container and
because of thisan algorithm will work for any type of element and we don't have todefine same
algorithm for different types of containers.

The above diagram shows to iterators i and j, pointing to thebeginning and the end
of a vector.

Defining an Iterator in STL

Syntax for defining an iterator is :

container_type <parameter_list>::iterator
iterator_name;

Let's see an example for understanding iterators in a better way:

#include<iostream>
#include<vector>

using namespace std;

int main()

vector<int>::iterator i;

/* create an iterator named i to a vector ofintegers */

vector<string>::iterator j;

/* create an iterator named j to a vector ofstrings */

list<int>::iterator k;

/* create an iterator named k to a vector ofintegers */

map<int, int>::iterator l;

/* create an iterator named l to a map ofintegers */

}
Iterators can be used to traverse the container, and we can de- reference the iterator to get
the value of the element it is pointingto. Here is an example:

#include<iostream>

#include<vector>

int main()

vector<int> v(10);

/* creates an vector v : 0,0,0,0,0,0,0,0,0,0


*/

vector<int>::iterator i;

for(i = v.begin(); i! = v.end(); i++)

cout << *i <<" ";

/* in the above for loop iterator I iteratesthough the

vector v and *operator is used of printing theelement

pointed by it. */
return 0;

Operations on Iterators in STL


Following are the operations that can be used with Iterators toperform various
actions.

 advance

 distance

 next

 prev

 begin

 end

advance() Operation

It will increment the iterator i by the value of the distance. If thevalue of distance is
negative, then iterator will be decremented.

SYNTAX: advance(iterator i ,int distance)

#include<iostream>

#include<vector>

int main()
{

vector<int> v(10) ; // create a vector of10 0's

vector<int>::iterator i; // defines aniterator i to the vector of integers

i = v.begin();

/* i now points to the beginning of the vectorv */

advance(i,5);

/* i now points to the fifth element form the

beginning of the vector v */

advance(i,-1);

/* i now points to the fourth element from


the

beginning of the vector */

}
distance() Operation

It will return the number of elements or we can say distancebetween the first and
the last iterator.

SYNTAX: distance(iterator first, iterator last)

#include<iostream>

#include<vector>

int main()

vector<int> v(10) ; // create a vector of


10 0's

vector<int>::iterator i, j; // defines
iterators i,j to the vector of integers

i = v.begin();

/* i now points to the beginning of the vector


v */

j = v.end();
/* j now points to the end() of the vector v
*/

cout << distance(i,j) << endl;

/* prints 10 , */

next() Operation

It will return the nth iterator to i, i.e iterator pointing to the nthelement from the
element pointed by i.

SYNTAX: next(iterator i ,int n)

prev() Operation

It will return the nth predecessor to i, i.e iterator pointing to the nthpredecessor element from
the element pointed by i.

SYNTAX: prev(iterator i, int n)

begin() Operation
This method returns an iterator to the start of the given container.SYNTAX: begin()

end() Operation

This method returns an iterator to the end of the given container.SYNTAX: end()

You might also like