LectureSlide For CPP
LectureSlide For CPP
Weeks 5 to 8
2
Course Content Source: CSE_BUET_UG_Course_Calendar_2022.pdf
• C++: Classes and objects: specifying a class, access specifiers; Functions: inline functions,
friend functions; Constructors and destructors; Operator overloading and type conversions;
Inheritance: single inheritance, multilevel inheritance, multiple inheritance; Polymorphism:
function overloading, virtual functions, pure virtual functions; Templates: class templates,
function templates, introduction to the standard template library (STL);
• Java: Nested and Inner classes; Local variable type inference; Strings: String, StringBuffer,
StringBuilder; Inheritance: abstract class and anonymous subclasses, object class; Access
protection with package; Interface; Exception; Thread: multithreading, Introduction to Java
concurrency utilities; Generics and collections; Stream API and lambda expressions;
Networking: ServerSocket, Socket
3
It’s time to Proceed to Contents
4
Templates
5
Templates
• Template is one of C++'s most sophisticated and high-powered features.
• Using templates, it is possible to create generic functions and classes.
• In a generic function or class, the type of data upon which the function or
class operates is specified as a parameter.
• It is possible to use one function or class with several different types of data without
having to explicitly recode specific versions for each data type.
6
Generic Functions
int main() // This is a function template
{ template <class X> void swapargs(X &a, X &b)
int i = 10, j = 20; {
double x = 10.1, y = 23.3; X temp;
char a = 'x', b = 'z'; temp = a;
cout << "Original i, j: " << i << ' ' << j << '\n'; a = b;
cout << "Original x, y: " << x << ' ' << y << '\n'; b = temp;
cout << "Original a, b: " << a << ' ' << b << '\n'; }
swapargs(i, j); // swap integers
swapargs(x, y); // swap floats
swapargs(a, b); // swap chars
cout << "Swapped i, j: " << i << ' ' << j << '\n';
cout << "Swapped x, y: " << x << ' ' << y << '\n';
cout << "Swapped a, b: " << a << ' ' << b << '\n';
return 0;
}
7
Generic Functions (2)
• A generic function defines a general set of operations that will be applied to
various types of data.
• The type of data that the function will operate upon is passed to it as a
parameter.
• Through a generic function, a single general procedure can be applied to a
wide range of data.
• Applicable for many algorithms are logically the same no matter what type
of data is being operated upon.
• For example, sorting algorithm
• In essence, a generic function is a function that can automatically overload
itself.
8
Generic Functions (3)
• A generic function is created using the keyword template.
• The normal meaning of the word "template" accurately reflects its use in C++.
• It is used to create a template (or framework) that describes what a function
will do, leaving it to the compiler to fill in the details as needed.
• The general form of a template function definition is shown here:
int main()
{
myfunc(10, "I like C++");
myfunc(98.6, 19L);
return 0;
}
10
Explicit Overloading of Generic Functions
template <class X> int main()
void swapargs(X &a, X &b) {
{ int i = 10, j = 20;
X temp; double x = 10.1, y = 23.3;
temp = a; char a = 'x', b = 'z';
a = b; cout << "Original i, j: " << i << ' ' << j << '\n';
b = temp; cout << "Original x, y: " << x << ' ' << y << '\n';
cout << "Inside template swapargs.\n"; cout << "Original a, b: " << a << ' ' << b << '\n';
} swapargs(i, j); // calls explicitly overloaded swapargs()
swapargs(x, y); // calls generic swapargs()
void swapargs(int &a, int &b) swapargs(a, b); // calls generic swapargs()
{ cout << "Swapped i, j: " << i << ' ' << j << '\n';
int temp; cout << "Swapped x, y: " << x << ' ' << y << '\n';
temp = a; cout << "Swapped a, b: " << a << ' ' << b << '\n';
a = b; return 0;
b = temp; }
cout << "Inside swapargs int specialization.\n";
}
11
Specialization Syntax for Overloading Generic Functions
template <class X> int main()
void swapargs(X &a, X &b) {
{ int i = 10, j = 20;
X temp; double x = 10.1, y = 23.3;
temp = a; char a = 'x', b = 'z';
a = b; cout << "Original i, j: " << i << ' ' << j << '\n';
b = temp; cout << "Original x, y: " << x << ' ' << y << '\n';
cout << "Inside template swapargs.\n"; cout << "Original a, b: " << a << ' ' << b << '\n';
} swapargs(i, j); // calls explicitly overloaded swapargs()
swapargs(x, y); // calls generic swapargs()
// Use new-style specialization syntax. swapargs(a, b); // calls generic swapargs()
template <> cout << "Swapped i, j: " << i << ' ' << j << '\n';
void swapargs<int>(int &a, int &b) cout << "Swapped x, y: " << x << ' ' << y << '\n';
{ cout << "Swapped a, b: " << a << ' ' << b << '\n';
int temp; return 0;
temp = a; }
a = b;
b = temp;
cout << "Inside swapargs int specialization.\n";
} 12
Overloading Function Templates
// First version of f() template. int main()
template <class X> {
void f(X a) f(10); // calls f(X)
{ f(10, 20); // calls f(X, Y)
cout << "Inside f(X a)\n"; return 0;
} }
13
Standard Parameters with Template Functions
const int TABWIDTH = 8; int main()
// Display data at specified tab position. {
template<class X> tabOut("This is a test", 0);
void tabOut(X data, int tab) tabOut(100, 1);
{ tabOut('X', 2);
for (; tab; tab--) tabOut(10 / 3, 3);
for (int i = 0; i < TABWIDTH; i++) return 0;
cout << ' '; }
cout << data << "\n";
}
14
Generic Function Restrictions
• Generic functions are similar to overloaded functions
except that they are more restrictive.
• When functions are overloaded, different actions can be
performed within the body of each function.
• But a generic function must perform the same general
action for all versions—only the type of data can differ.
15
Application of Generic Function – Generic Sort
template <class X> int main()
void bubble( {
X *items, // pointer to array to be sorted int iarray[7] = {7, 5, 4, 3, 9, 8, 6};
int count) // number of items in array double darray[5] = {4.3, 2.5, -0.9, 100.2, 3.0};
{ int i;
register int a, b; cout << "Here is unsorted integer array: ";
X t; for (i = 0; i < 7; i++) cout << iarray[i] << ' ';
for (a = 1; a < count; a++) cout << endl;
for (b = count - 1; b >= a; b--) cout << "Here is unsorted double array: ";
if (items[b - 1] > items[b]) for (i = 0; i < 5; i++) cout << darray[i] << ' ';
{ cout << endl;
// exchange elements bubble(iarray, 7);
t = items[b-1]; bubble(darray, 5);
items[b-1] = items[b]; cout << "Here is sorted integer array: ";
items[b] = t; for (i = 0; i < 7; i++) cout << iarray[i] << ' ';
} cout << endl;
} cout << "Here is sorted double array: ";
for (i = 0; i < 5; i++) cout << darray[i] << ' ';
cout << endl;
return 0;
} 16
Generic Classes
const int SIZE = 10; template <class StackType>
// Create a generic stack class void stack<StackType>::push(StackType ob)
template <class StackType> class stack {
{ if (tos == SIZE) {
StackType stck[SIZE]; // holds the stack cout << "Stack is full.\n";
int tos; // index of top-of-stack return;
public: }
stack() { tos = 0; } // initialize stack stck[tos] = ob;
void push(StackType ob); // push object on stack tos++;
StackType pop(); // pop object from stack }
};
template <class StackType>
StackType stack<StackType>::pop()
{
if (tos == 0) {
cout << "Stack is empty.\n";
return 0; // return null on empty stack
}
tos--;
return stck[tos];
} 17
Generic Classes (2)
• A generic class defines all the algorithms used by that class
• The actual type of the data being manipulated are specified as a parameter when
objects of that class are created.
• Generic classes are useful when a class uses logic that can be generalized.
• For example, stack, queue
• The compiler will automatically generate the correct type of object, based upon
the type specified when the object is created.
• The general form of a generic class declaration is shown here:
template <class Ttype>
class class-name {
.
.
.
};
• Once you have created a generic class, you create a specific instance of that class
using the following general form: class-name <type> ob; 18
Generic Classes with Multiple Types
template <class Type1, class Type2> int main()
class myclass {
{ myclass<int, double> ob1(10, 0.23);
Type1 i; myclass<char, char *> ob2('X', "Templates add power.");
Type2 j; ob1.show(); // show int, double
ob2.show(); // show char, char *
public: return 0;
myclass(Type1 a, Type2 b) }
{
i = a;
j = b;
}
void show() { cout << i << ' ' << j << '\n'; }
};
19
Applications of Generic Classes
const int SIZE = 10; // Provide range checking for atype. int main()
template <class AType> template <class AType> {
class atype AType &atype<AType>::operator[](int i) atype<int> intob; // integer array
{ { atype<double> doubleob; // double array
AType a[SIZE]; if (i < 0 || i > SIZE - 1) int i;
{ cout << "Integer array: ";
public: cout << "\nIndex value of "; for (i = 0; i < SIZE; i++) intob[i] = i;
atype() cout << i << " is out-of-bounds.\n"; for (i = 0; i < SIZE; i++)
{ exit(1); cout << intob[i] << " ";
register int i; } cout << '\n';
for (i = 0; i < SIZE; i++) a[i] = i; return a[i]; cout << "Double array: ";
} } for (i = 0; i < SIZE; i++)
AType &operator[](int i); doubleob[i] = (double)i / 3;
}; for (i = 0; i < SIZE; i++)
cout << doubleob[i] << " ";
cout << '\n';
intob[12] = 100; // generates runtime
error
return 0;
} 20
Non-Type Arguments with Generic int main()
{
Classes atype<int, 10> intob; // integer
array of size 10
template <class AType, int size> // Provide range checking for atype. atype<double, 15> doubleob; //
class atype template <class AType, int size> double array of size 15
{ AType &atype<AType, size>::operator[](int i) int i;
AType a[size]; // length of array { cout << "Integer array: ";
is passed in size if (i < 0 || i > size - 1) for (i = 0; i < 10; i++)
public: { intob[i] = i;
atype() cout << "\nIndex value of "; for (i = 0; i < 10; i++)
{ cout << i << " is out-of-bounds.\n"; cout << intob[i] << " ";
register int i; exit(1); cout << '\n';
for (i = 0; i < size; i++) } cout << "Double array: ";
a[i] = i; return a[i]; for (i = 0; i < 15; i++)
} } doubleob[i] = (double)i / 3;
AType &operator[](int i); for (i = 0; i < 15; i++)
}; cout << doubleob[i] << " ";
cout << '\n';
intob[12] = 100; // generates
runtime error
return 0;
}
21
Default Arguments in Generic Classes
template <class AType = int, int size = 10> int main() {
class atype atype<int, 100> intarray; // integer array, size 100
{ atype<double> doublearray; // double array, default size
AType a[size]; // size of array is passed in size atype<> defarray; // default to int array of size 10
public: int i;
atype() { cout << "int array: ";
register int i; for (i = 0; i < 100; i++) intarray[i] = i;
for (i = 0; i < size; i++) a[i] = i; for (i = 0; i < 100; i++) cout << intarray[i] << " ";
} cout << '\n';
AType &operator[](int i); cout << "double array: ";
}; for (i = 0; i < 10; i++) doublearray[i] = (double)i / 3;
for (i = 0; i < 10; i++) cout << doublearray[i] << " ";
template <class AType, int size> cout << '\n';
AType &atype<AType, size>::operator[](int i){ cout << "defarray array: ";
if (i < 0 || i > size - 1) { for (i = 0; i < 10; i++)
cout << "\nIndex value of "; defarray[i] = i;
cout << i << " is out-of-bounds.\n"; for (i = 0; i < 10; i++)
exit(1); cout << defarray[i] << " ";
} cout << '\n';
return a[i]; return 0;
} } 22
Template Class Specialization
template <class T> // Explicit specialization for int. int main()
class myclass template <> {
{ class myclass<int> myclass<double> d(10.1);
T x; { cout << "double: " << d.getx() << "\n\n";
int x; myclass<int> i(5);
public: cout << "int: " << i.getx() << "\n";
myclass(T a) public: return 0;
{ myclass(int a) }
cout << "Inside generic myclass\n"; {
x = a; cout << "Inside myclass<int>
} specialization\n";
T getx() { return x; } x = a * a;
}; }
int getx() { return x; }
};
23
Typename Keyword
template <class X> template <typename X>
void swapargs(X &a, X &b) void swapargs(X &a, X &b)
{ {
X temp; X temp;
temp = a; temp = a;
a = b; a = b;
b = temp; b = temp;
} }
24
Standard Template Library
(STL)
26
Introduction to STL
• Developed by Alexander Stepanov and Meng Lee at Hewlett-
Packard Lab
- as proof-of-concept for so-called generic programming.
• Released in 1994 and subsequently adopted into the C++98.
• STL provides general-purpose, templatized classes and functions
that implement
- many popular and commonly used algorithms and
- data structures, including, for example, support for
vectors, lists, queues, and stacks.
• It also defines various routines that access them.
• Because the STL is constructed from template classes, the
algorithms and data structures can be applied to nearly any type
of data. 27
STL Templates
Container Iterator
Templatized data structure. Can be used to A generalization of pointer. An object that
hold fundamental-type values or almost any allows traversing through elements of a
type of objects, e.g., vector<int>, list<string>, container, e.g., vector<int>::iterator,
deque<Person>. list<string>:: iterator.
Algorithms Function
Used for tasks such as searching, sorting and
comparison, e.g., for_each, find, sort.
Objects
Objects that act like functions.
28
Types of Containers
Sequence Containers Container Adapter Classes
linear data structures of elements constrained sequence containers
array (C++ 11): NOT a STL container because it Stack: Last-in-first-out (LIFO) queue, adapted
has a fixed size and does not support operations like from deque (default), or vector, or list. Support
insert. But STL algorithms can be applied. operations back, push_back, pop_back.
vector: dynamically resizable array. Support fast queue: First-in-first-out (FIFO) queue, adapted
insertion and deletion at back; and direct access to its from deque (default), or list. Support
elements. operations front, back, push_back, pop_front.
deque: double-ended queue. Support fast insertion priority_queue: highest priority element at
and deletion at front and back; and direct access to its front of the queue. adapted from vector (default)
elements. or deque. Support
forward_list (C++ 11): single-linked list that operations front, push_back, pop_front.
support forward transversal only. It is simpler than list.
list: double-linked list. Support fast insertion and
deletion anywhere in the list; and direct access to its
elements. 29
Types of Containers (2)
Associative Containers Unordered Associative Containers
nonlinear data structures storing key-value pairs, sorted based on hash table, efficient in insertion, removal and
by keys search but requires more storage
set: No duplicate element. Support fast lookup. unordered_set: No duplicate element. Support fast
lookup.
multiset: Duplicate element allowed. Support fast
lookup. unordered_multiset: Duplicate element allowed.
Support fast lookup.
map: One-to-one mapping (associative array) with no
duplicate. Support fast key lookup. unordered_map: One-to-one mapping (associative
array) with no duplicate. Support fast key lookup.
multimap: One-to-many mapping, with duplicates
allowed. Support fast key lookup. Unordered_multimap: One-to-many mapping,
with duplicates allowed. Support fast key lookup.
C++ 11
30
Flowchart of Sequence and Ordered Containers
start
31
Ref: https://www.geeksforgeeks.org/containers-cpp-stl/
Flowchart of Adaptive and Unordered Containers
start
32
Ref: https://www.geeksforgeeks.org/containers-cpp-stl/
Types of Containers
Simple Containers Other Container Classes
pair: bitset: stores series of bits similar to a fixed-sized
• The pair container is a simple associative container vector of bools. Implements bitwise operations and
consisting of a 2-tuple of data elements or objects, lacks iterators. Not a sequence. Provides random
called 'first' and 'second', in that fixed order. access.
• The STL 'pair' can be assigned, copied and
compared.
valarray: Another array data type, intended for
• The array of objects allocated in a map or hash_map numerical use (especially to represent vectors and
matrices); the C++ standard allows specific
are of type 'pair' by default, where all the 'first'
optimizations for this intended purpose.
elements act as the unique keys, each associated
with their 'second' value objects.
33
Container Functions
All containers provides these functions: In addition, the first-class containers support
• Default Constructor: to construct an these functions:
empty container. Other constructors are • begin, end, cbegin, cend: Returns the
provided for specific purposes. begin and end iterator, or the const
• Copy Constructor version.
• Destructor • rbegin, rend, crbegin, crend: Returns the
• empty(): returns true if the container is reverse_iterator.
empty. • clear(): Removes all elements.
• size(): returns the size (number of • erase(): Removes one element given an
elements). iterator, or a range of elements given
• Assignment Operator (=) [begin, end) iterators.
• Comparison Operators (==, !=, <, <=, >, • max_size(): Returns the maximum number
>=). of elements that the container can hold.
• swap(): exchanges the contents of two
containers.
34
Container Headers
<vector> <valarray>
<list> <bitset>
<deque> <array> (C++11)
<queue>: queue and priority_queue <forward_list> (C++11)
<stack> <unordered_map> (C++11)
<map>: map and multimap <unordered_set> (C++11)
<set>: set and multiset
In addition to the headers required by the various STL classes, the C++ standard
library includes the <utility> and <functional> headers, which provide support for
the STL. For example, the template class pair, which can hold a pair of values, is
defined in <utility>.
35
Iterators
• An iterator behaves like a generic pointer, that can be used to
- reference (point-to) individual element of a generic container; and
- transverse through elements of a container.
• The purpose of iterator is to make traversing (iterating) of containers
independent on the type of the containers (e.g., vector<int>,
queue<double>, stack<string>).
• With iterator, it is possible apply generic algorithm (such as searching,
sorting and comparison) to the container, independent of types.
36
Requirements of Iterators
• The dereferencing operator * shall be defined.
- if iter is an iterator, *iter shall be pointing to an element of the container.
• The assignment operator = shall be defined.
- if iter1 and iter2 are iterators, iter1 = iter2 shall assign iter2 to iter1.
• The comparison operators == and != shall be defined.
- if iter1 and iter2 are iterators, we can use iter1 == iter2 and iter1 !=
iter2 to compare them for equality.
- iter1 == iter2 is true, then they shall be pointing at the same element,
i.e., *iter1 == *iter2.
37
Requirements of Iterators
• The increment operator ++ shall be defined.
- if iter is an iterator, ++iter and iter++ move the iterator to point to the
next element.
- The program shall be able to iterate through all the elements via ++iter
(or iter++) operations.
• For linearly-ordered container, the + (and +=) operator shall be defined.
- if iter is an iterator, iter+n points to the next n-th element in the linear
order.
• For iterator that can transverse backward, the decrement operator -- shall be
defined.
- if iter is an operator, --iter and iter-- move the iterator to point to the next
element in the reverse order (or previous element in the forward order).
38
Working with Iterators
• All STL container provides two member functions:
- begin() and end() that return the iterators pointing to the first
element and the pass-the-end element respectively.
• Hence, the following code to transverse all the elements in the container:
• In C++11, you can also use the new for-each loop to iterate thru all the
element of a container:
41
Vector Basics
// Demonstrate a vector. /* put more values onto the end of the vector, it will grow as
#include <iostream> needed */
#include <vector> Header file for vector cout << "Expanding vector\n";
#include <cctype> for (i = 0; i < 5; i++)
using namespace std; v.push_back(i + 10 + 'a'); Insert at the end
int main() // display current size of v
Create a vector of type char
{ cout << "Size now = " << v.size() << endl;
vector<char> v(10); // create a vector of length 10 cout << "Capacity = " << v.capacity() << endl;
unsigned int i; // display contents of vector
// display original size of v Get the size of vector cout << "Current contents:\n";
cout << "Size = " << v.size() << endl; Get the capacity for (i = 0; i < v.size(); i++) What would be the
cout << "Capacity = " << v.capacity() << endl; cout << v[i] << " "; value of capacity here?
// assign the elements of the vector some values cout << "\n\n";
for (i = 0; i < 10; i++) // change contents of vector
v[i] = i + 'a'; for (i = 0; i < v.size(); i++)
// display contents of vector Access vector like an array v[i] = toupper(v[i]);
cout << "Current Contents:\n"; cout << "Modified Contents:\n";
for (i = 0; i < v.size(); i++) for (i = 0; i < v.size(); i++)
cout << v[i] << " "; cout << v[i] << " ";
cout << "\n\n"; cout << endl;
} 42
Iterator with Vector
#include <iostream> // display contents of vector // display contents of vector
#include <vector> cout << "Original contents:\n"; cout << "Modified Contents:\n";
#include <cctype> p = v.begin(); p = v.begin();
using namespace std; while (p != v.end()) while (p != v.end())
int main() { {
{ cout << *p << " "; cout << *p << " ";
vector<char> v(10); create an p++; p++;
// create an iterator iterator } }
vector<char>::iterator p; cout << "\n\n"; cout << endl;
int i; // change contents of vector return 0;
// assign elements in vector a value p = v.begin(); }
p = v.begin() Initialize (like a pointer) while (p != v.end())
i = 0; {
while (p != v.end()) *p = toupper(*p);
{ p++;
*p = i + 'a'; Access through Iterator }
p++;
i++; Advance to next element
}
Auto Type Deduction of Iterators in C++11
// Access the elements of a vector through an iterator. // Access the elements of a vector through an iterator.
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <cctype> #include <cctype>
using namespace std; using namespace std;
int main() { int main() {
vector<char> v(10); // create a vector of length 10 vector<char> v(10); // create a vector of length 10
int i=0; int i=0;
for (auto p = v.begin(); p != v.end(); ++p) { for (auto p = v.begin(); p != v.end(); ++p) {
*p = i + 'a'; *p = i + 'a';
i++; i++;
} }
// display contents of vector // display contents of vector
cout << "Original contents:\n"; cout << "Original contents:\n";
for (auto p = v.begin(); p != v.end(); ++p) { for (auto p : v) {
cout << *p << " "; cout << p << " ";
} Use of auto } for_each
cout << "\n\n"; cout << "\n\n";
return 0; return 0;
} }
Insert and Erase in Vector
#include <iostream> vector<char>::iterator p = v.begin(); // Insert v2 into v Insert from vector
#include <vector> p += 2; // point to 3rd element v.insert(p, v2.begin(), v2.end());
using namespace std; // insert 10 X's into v cout << "Size after v2's insertion = ";
int main() { v.insert(p, 10, 'X'); Insert elements cout << v.size() << endl;
vector<char> v(10); // display contents after insertion cout << "Contents after insert:\n";
vector<char> v2; cout << v.size() << endl; for (i = 0; i < v.size(); i++)
char str[] = "<Vector>"; cout << "Contents after insert:\n"; cout << v[i] << " ";
unsigned int i; for (i = 0; i < v.size(); i++) cout << endl;
// initialize v cout << v[i] << " "; return 0;
for (i = 0; i < 10; i++) cout << "\n\n"; }
v[i] = i + 'a'; // remove those elements
// copy characters in str into v2 p = v.begin();
for (i = 0; str[i]; i++) p += 2; // point to 3rd element
v2.push_back(str[i]); // remove next 10 elements
// display original contents of vector v.erase(p, p + 10); Erase from vector
cout << "Original contents of v:\n"; // display contents after deletion
for (i = 0; i < v.size(); i++) cout << v.size() << endl;
cout << v[i] << " "; cout << "Contents after erase:\n";
cout << "\n\n"; for (i = 0; i < v.size(); i++)
cout << v[i] << " ";
cout << "\n\n";
Store Objects in Vector
#include <iostream> int main() Create a vector of objects
#include <vector> {
#include <cstdlib> vector<DailyTemp> v;
using namespace std; unsigned int i; Insert objects
class DailyTemp { for (i = 0; i < 7; i++)
int temp; v.push_back(DailyTemp(60 + rand() % 30));
public: cout << "Fahrenheit temperatures:\n";
DailyTemp() { temp = 0; } for (i = 0; i < v.size(); i++) Access member function
DailyTemp(int x) { temp = x; } cout << v[i].get_temp() << " ";
DailyTemp &operator=(int x) { cout << endl;
temp = x; // convert from Fahrenheit to Centigrade
return *this; for (i = 0; i < v.size(); i++)
} v[i] = (int)(v[i].get_temp() - 32) * 5 / 9;
double get_temp() { return temp; } cout << "Centigrade temperatures:\n";
}; for (i = 0; i < v.size(); i++)
bool operator<(DailyTemp a, DailyTemp b) {
return a.get_temp() < b.get_temp(); cout << v[i].get_temp() << " ";
} return 0;
bool operator==(DailyTemp a, DailyTemp b) { }
return a.get_temp() == b.get_temp();
}
Functions in Vector Template Class
Constructors
vector (const allocator_type & alloc = allocator_type()); // Default Constructor: construct a vector object
vector (size_type n, const value_type & val = value_type(), const allocator_type & alloc = allocator_type()); // Fill
Constructor: construct a vector object with n-element filled with val
vector (const vector & v); // Copy Constructor
template <class InputIterator> vector (InputIterator first, InputIterator last, const allocator_type & alloc =
allocator_type()); // Range Copy Constructor
Iterator-based Operations
iterator insert (iterator pos, const value_type & val); // Single-Element: insert element val before iterator pos
void insert (iterator pos, size_type n, const value_type & val); // Fill: insert n copies of val before pos
template <class InputIterator>
void insert (iterator pos, InputIterator first, InputIterator last)
// Range-copy: copy the range [first, last) and insert before pos.
iterator erase (iterator pos); // Single-element: remove element pointed to by iterator pos
iterator erase (iterator first, iterator last); // Range: remove elements between [first,last)
void assign (size_type n, const value_type & val); // Fill: clear old contents and assign n copies of val
template <class InputIterator>
void assign (InputIterator first, InputIterator last); // Range: assign [first, last)
The List Template Class
• list is a class template, declared in the list header.
• The list class supports a bidirectional, linear list.
• Unlike a vector, which supports random access, a list can be
accessed sequentially only.
• Since lists are bidirectional, they may be accessed front to back
or back to front.
50
List Basics
// List basics. // change contents of list
#include <iostream> p = lst.begin();
#include <list> while (p != lst.end())
using namespace std; {
int main() Create a list of integers *p = *p + 100;
{ p++;
list<int> lst; // create an empty list }
int i; cout << "Contents modified: ";
for (i = 0; i < 10; i++) p = lst.begin();
lst.push_back(i); Insert elements while (p != lst.end())
cout << "Size = " << lst.size() << endl; {
cout << "Contents: "; cout << *p << " ";
list<int>::iterator p = lst.begin(); p++;
while (p != lst.end()) }
{ return 0;
cout << *p << " "; Access with iterator }
p++;
}
cout << "\n\n";
// Understanding end().
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> lst; // create an empty list
?drawkcab
How wouldtsil
youa print
tnirp int i;
for (i = 0; i < 10; i++)
auoy
listdluow
backward?
woH lst.push_back(i);
cout << "List printed backwards:\n";
list<int>::iterator p = lst.end();
?
while (p != lst.begin()) {
p--; // decrement pointer before using
cout << *p << " ";
}
return 0;
}
Push_Back() and Push_Front()
/* Demonstrating the difference between list<int>::iterator p;
push_back() and push_front(). */ cout << "Contents of lst1:\n";
#include <iostream> p = lst1.begin();
#include <list> while (p != lst1.end())
using namespace std; {
int main() cout << *p << " ";
{ p++;
list<int> lst1, lst2; }
int i; cout << "\n\n";
for (i = 0; i < 10; i++) cout << "Contents of lst2:\n";
lst1.push_back(i); p = lst2.begin();
for (i = 0; i < 10; i++) while (p != lst2.end())
lst2.push_front(i); {
cout << *p << " ";
p++;
}
return 0;
}
Sort a List
// Sort a list. // sort the list
#include <iostream> lst.sort(); Sort list
#include <list> cout << "Sorted contents:\n";
#include <cstdlib> p = lst.begin();
using namespace std; while (p != lst.end())
int main() {
{ cout << *p << " ";
list<int> lst; p++;
int i; }
// create a list of random integers return 0;
for (i = 0; i < 10; i++) }
lst.push_back(rand());
cout << "Original contents:\n";
list<int>::iterator p = lst.begin();
while (p != lst.end()) {
cout << *p << " ";
p++;
}
cout << endl << endl;
Merge Two Lists
// Merge two lists. cout << "Contents of lst2:\n";
#include <iostream> p = lst2.begin();
#include <list> while (p != lst2.end()) {
using namespace std; cout << *p << " ";
int main() { p++;
list<int> lst1, lst2; }
int i; cout << endl << endl;
for (i = 0; i < 10; i += 2) lst1.push_back(i); // now, merge the two lists
for (i = 1; i < 11; i += 2) lst2.push_back(i); lst1.merge(lst2); Merge lists
cout << "Contents of lst1:\n"; if (lst2.empty()) cout << "lst2 is now empty\n";
list<int>::iterator p = lst1.begin(); cout << "Contents of lst1 after merge:\n";
while (p != lst1.end()) { p = lst1.begin();
cout << *p << " "; while (p != lst1.end()) {
p++; cout << *p << " ";
} p++;
cout << endl << endl; }
return 0;
}
Store Objects in List
class myclass { int main() {
int a, b, sum; Mandatory
int i;
public: list<myclass> lst1; // create first list
myclass() { a = b = 0; } for (i = 0; i < 10; i++) lst1.push_back(myclass(i, i));
myclass(int i, int j) { cout << "First list: ";
a = i; b = j; sum = a + b; list<myclass>::iterator p = lst1.begin();
} Mandatory while (p != lst1.end()) { cout << p->getsum() << " "; p++; }
int getsum() { return sum; } cout << endl;
friend bool operator<(const myclass &o1, const myclass &o2) { list<myclass> lst2; // create a second list
return o1.sum < o2.sum; for (i = 0; i < 10; i++) lst2.push_back(myclass(i * 2, i * 3));
} cout << "Second list: ";
friend bool operator>(const myclass &o1, const myclass &o2) { p = lst2.begin();
return o1.sum > o2.sum; while (p != lst2.end()) { cout << p->getsum() << " "; p++; }
} cout << endl;
friend bool operator==(const myclass &o1, const myclass &o2) { lst1.merge(lst2); // now, merget lst1 and lst2
return o1.sum == o2.sum; cout << "Merged list: ";
} p = lst1.begin();
friend bool operator!=(const myclass &o1, const myclass &o2) { while (p != lst1.end()) { cout << p->getsum() << " "; p++; }
return o1.sum != o2.sum; return 0;
} }
};
The Stack Template Class
• A container adaptor that permits LIFO access #include <iostream>
#include <stack>
• Uses vector, deque (by default) or list as using namespace std;
underlying container int main() {
stack<int> stack;
• Defined in header stack stack.push(21);
stack.push(22);
template <class Type, class Container = deque<Type> >
stack.push(24);
class stack;
stack.push(25);
int num = 0;
• Supported functions are stack.push(num);
• empty() stack.pop();
stack.pop();
• size()
stack.pop();
• top()
• push(), emplace(C++11), push_range (C+ while (!stack.empty()) {
cout << stack.top() << " ";
+23) stack.pop();
• pop() }
• swap (C++11) }
57
The Queue Template Class
• A container adaptor that permits FIFO access #include <iostream>
#include <queue>
• Uses deque (by default) or list as underlying using namespace std;
container // Print the queue
void print_queue(queue<int> q){
• Defined in header queue queue<int> temp = q;
template <class Type, class Container = deque<Type> > while (!temp.empty()) {
class queue; cout << temp.front()<<“ "<<temp.back()<<'\n';
temp.pop();
• Supported functions are }
• front() cout << '\n';
}
• back()
int main(){
• empty() queue<int> q1;
• size() q1.push(1);
q1.push(2);
• push(), emplace(C++11), push_range (C+ q1.push(3);
+23) cout << "The first queue is : ";
• pop() print_queue(q1);
return 0;
• swap() } 58
The Priority Queue Template Class
• A container adaptor that provides constant #include <iostream>
time lookup of the largest (by default) or #include <queue>
using namespace std;
smallest element int main(){
• Uses vector (by default) as underlying priority_queue<int> q;
container q.push(1);
q.push(2);
• Defined in header queue q.push(3);
cout << "The priority queue is : ";
template< class T, class Container = std::vector<T>,
while (!q.empty()) {
class Compare = std::less<typename Container::value_type>
cout << q.top() <<" ";
> class priority_queue;
q.pop();
• Supported functions are }
cout << '\n';
• empty()
return 0;
• size() }
• top()
• push(), emplace(C++11)
• pop()
59
The Pair Template Class teach yourself: tuple class
#include <iostream> #include <iostream>
#include <utility> #include <utility>
using namespace std; using namespace std;
int main(){ int main(){
pair<int, char> PAIR1; pair<char, int> pair1 = make_pair('A', 1);
pair<string, double> PAIR2("GeeksForGeeks", 1.23); pair<char, int> pair2 = make_pair('B', 2);
pair<string, double> PAIR3;
PAIR1.first = 100; cout << "Before swapping:\n ";
PAIR1.second = 'G'; cout << "Contents of pair1 = " << pair1.first << " "
PAIR3 = make_pair("GeeksForGeeks is Best", 4.56); << pair1.second;
cout << PAIR1.first << " "; cout << "Contents of pair2 = " << pair2.first << " "
cout << PAIR1.second << endl; << pair2.second;
cout << PAIR2.first << " "; pair1.swap(pair2);
cout << PAIR2.second << endl;
cout << PAIR3.first << " "; cout << "\nAfter swapping:\n ";
cout << PAIR3.second << endl; cout << "Contents of pair1 = " << pair1.first << " "
<< pair1.second;
return 0; cout << "Contents of pair2 = " << pair2.first << " "
} << pair2.second;
return 0;
} 60
The Map Template Class
• The map class supports an associative container in which unique keys are
mapped with values.
• In essence, a key is simply a name that is given to a value.
• Once a value has been stored, it can be retrieved by using its key.
• Thus, in its most general sense, a map is a list of key/value pairs.
• A map can hold only unique keys. Duplicate keys are not allowed.
• To create a map that allows nonunique keys, use multimap.
61
Map Basics
// A simple map demonstration. char ch;
#include <iostream> cout << "Enter key: ";
#include <map> cin >> ch;
using namespace std; map<char, int>::iterator p;
int main() // find value given key
{ p = m.find(ch);
map<char, int> m; if (p != m.end())
int i; cout << "Its ASCII value is " << p->second;
// put pairs into map else
for (i = 0; i < 26; i++) cout << "Key not in map.\n";
{ return 0;
m.insert(pair<char, int>('A' + i, 65 + i)); }
}
Application of Maps
// Use a map to create a phone directory. int main(){
#include <iostream> map<name, phoneNum> directory;
#include <map> // put names and numbers into map
#include <cstring> directory.insert(pair<name, phoneNum>(name("Tom"), phoneNum("555-4533")));
using namespace std; directory.insert(pair<name, phoneNum>(name("Chris"), phoneNum("555-
class name { 9678")));
char str[40]; directory.insert(pair<name, phoneNum>(name("John"), phoneNum("555-8195")));
public: directory.insert(pair<name, phoneNum>(name("Rachel"), phoneNum("555-
name() { strcpy(str, ""); } 0809")));
name(char *s) { strcpy(str, s); } // given a name, find number
char *get() { return str; } char str[80];
}; cout << "Enter name: ";
// Must define less than relative to name objects. cin >> str;
bool operator<(name a, name b) { map<name, phoneNum>::iterator p;
return strcmp(a.get(), b.get()) < 0; p = directory.find(name(str));
} if (p != directory.end())
class phoneNum { cout << "Phone number: " << p->second.get();
char str[80]; else
public: cout << "Name not in directory.\n";
phoneNum() { strcmp(str, ""); } return 0;
phoneNum(char *s) { strcpy(str, s); } }
char *get() { return str; }
};
Algorithms in STL
• The STL defines a large number of algorithms for a variety of purposes (e.g.
searching, sorting, counting, manipulating) that operate on ranges of elements.
• All of the algorithms are non-member template functions. This means that they
can be applied to any type of container.
• The algorithms operate on elements of STL container only indirectly through the
iterator. It accepts a pair of iterators, denoted as first and last, that mark the
range of operation as [first,last) (including first, but excluding last). For example,
sort(aVector.begin(), aVector.end()); // Sort the entire vector
sort(aVector.begin(), aVector.begin + aVector.size()/2); // Sort first half
84
Ref: https://www3.ntu.edu.sg/home/ehchua/programming/cpp/cp10_IO.html
Template Instantiations and typedef
• the basic_xxx template classes can be instantiated with a character type,
such as char and wchar_t.
• C++ further provides typedef statements to name these classes
85
C++ Predefined Streams
• When a C++ program begins execution, four built-in streams are
automatically opened. They are:
86
Formatted I/O
• C++ provides both the formatted and unformatted IO functions.
• In formatted or high-level IO, bytes are grouped and converted to types
such as int, double, string or user-defined types.
• In unformatted or low-level IO, bytes are treated as raw bytes and
unconverted.
• Formatted IO operations are supported via overloading the stream insertion
(<<) and stream extraction (>>) operators, which presents a consistent
public IO interface.
87
Formatted I/O
• The C++ I/O system allows to format I/O operations, such as
• set a field width,
• specify a number base, or
• determine how many digits after the decimal point will be displayed.
• There are two related but conceptually different ways to format
data.
1. Directly access members of the ios class. Specifically,
• setting various format status flags defined inside the ios class or
• calling various ios member functions.
2. Using special functions called manipulators that can be included as
part of an I/O expression.
88
Formatting Using ios Members
#include <iostream>
Flags using namespace std;
int main(){
• Adjustfield, • oct, cout.setf(ios::showpoint);
• • cout.setf(ios::showpos);
basefield, right, cout << 100.0 <<"\n"; // displays +100.000
• boolalpha, • scientific,
• dec, • Showbase, cout.setf(ios::uppercase | ios::scientific);
cout << 100.12 <<"\n"; // displays 1.001200E+02
• Fixed, • showpoint, cout.unsetf(ios::uppercase); // clear uppercase
• floatfield, • showpos, cout << 100.12 <<"\n"; // displays 1.001200e+02
• hex, • skipws, cout.unsetf(ios::showpos | ios::uppercase | ios::scientific);
• internal, • Unitbuf, cout.precision(4);
• • cout.width(10);
Left, uppercase cout << 10.12345 << "\n"; // displays 10.12
cout.fill('*');
Functions
cout.width(10);
cout << 10.12345 << "\n"; // displays *****10.12
// field width applies to strings, too
• width( ), cout.width(10);
• precision( ), and cout << "Hi!" << "\n"; // displays *******Hi!
cout.width(10);
• fill( ) cout.setf(ios::left); // left justify
cout << 10.12345; // displays 10.12*****
return 0;
} 89
Formatting Using Manipulators
#include <iostream>
C++ Manipulators #include <iomanip>
using namespace std;
• boolalpha • oct int main()
• dec • resetiosflags (fmtflags f) {
• endl • right cout << hex << 100 << endl;
• ends • scientific cout << setfill('?') << setw(10) << 2343.0;
• fixed • setbase(int base) cout << setiosflags(ios::showpos);
• flush • setfill(int ch) cout << setiosflags(ios::showbase);
• hex • setiosflags(fmtflags f) cout << 123 << " " << hex << 123;
• internal • setprecision (int p)
bool b;
• left • setw(int w) b = true;
• nobooalpha • showbase cout << b << " " << boolalpha << b << endl;
• noshowbase • showpoint cout << "Enter a Boolean value: ";
• noshowpoint • showpos cin >> boolalpha >> b;
cout << "Here is what you entered: " << b;
• noshowpos • skipws }
• noskipws • unitbuf
• nounitbuf • uppercase
• nouppercase • ws
90
Overloading << and >>
• The << and the >> operators are overloaded in C++ to perform I/O
operations on C++'s built-in types.
• It is possible to overload these operators so that they perform I/O
operations on types that you create.
• In the language of C++, the << output operator is referred to as the
insertion operator because it inserts characters into a stream.
• Likewise, the >> input operator is called the extraction operator because it
extracts characters from a stream.
• The functions that overload the insertion and extraction operators are
generally called inserters and extractors, respectively.
91
Creating Custom Inserter and Extractor
#include <iostream> int main()
using namespace std; {
class myclass myclass ob1, ob2;
{ cin >> ob1 >> ob2;
int x, y; cout << ob1 << ob2;
public: return 0;
friend ostream &operator<<(ostream &out, myclass& ob); }
friend istream &operator>>(istream &in, myclass& ob);
};
istream &operator>>(istream &in, myclass& ob)
{
in >> ob.x >> ob.y;
return in;
} inserter
92
C++ File I/O
• A computer file is stored on a secondary storage device (e.g., disk)
• permanent
• can be used to
• provide input data to a program
• or receive output data from a program
• or both;
• should reside in project directory for easy access;
• must be opened before it is used
93
C++ File I/O
• C++ provides three 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
• Done with the same operations (insertion, extraction) as keyboard input
and monitor output
• Simply open input or output object with connection to a file and use it
where you would use cin or cout
94
C++ File I/O
• To work with files one needs to -
• include <fstream>
95
C++ File I/O
• A file needs to be opened by ifstream before read or ofstream to write or
fstream to read and write
96
C++ File I/O
• The value of mode determines how the file is opened
• Type openmode is an enumeration defined by ios that contains the
following values:
• ios::app
• ios::ate
• ios::binary
• ios::in
• ios::out
• ios::trunc
• You can combine two or more of these value together by ORing them
• If open() fails the stream will evaluate to false
97
C++ File I/O: Writing and Reading
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
using namespace std; using namespace std;
int main() int main()
{ {
ofstream myfile; char ch;
myfile.open("example.txt"); ifstream myfile("example.txt");
myfile << "Writing this to a file.\n"; if (myfile.is_open())
myfile.close(); {
return 0; while (!myfile.eof())
} {
myfile >> ch;
cout << ch;
}
cout << endl;
myfile.close();
}
else
cout << “Unable to open file” return 0;
return 0;
}
98
C++ File I/O: Writing and Reading (Unformatted Binary)
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <cstdlib> #include <cstdlib>
using namespace std; using namespace std;
int main() int main()
{ {
char str[100] = "I love Bangladesh"; char ch;
ofstream out("myfile.txt", ios::out | ifstream in("myfile.txt", ios::in |
ios::binary); ios::binary);
if (!out.is_open()) if (!in.is_open())
{ {
cout << "Cannot open file" << endl; cout << "Cannot open file" << endl;
exit(1); exit(1);
} }
for (int i = 0; str[i]; i++) while (!in.eof())
out.put(str[i]); {
out.close(); in.get(ch);
cout << ch;
return 0; }
} cout << endl;
in.close();
return 0;
} 99
C++ File I/O (Unformatted Binary) Random Access
• istream &seekg(off_type offset, seekdir origin)
• A member function of ifstream and fstream
• Moves the current get pointer offset number of bytes from the specified origin
• ostream &seekp(off_type offset, seekdir origin)
• A member function of ofstream and fstream
• Moves the current put pointer offset number of bytes from the specified origin
• seekdir is an enumeration defined in ios with the following values:
• ios::beg
• ios::cur
• ios::end
100
C++ File I/O (Unformatted Binary) Random Access
• pos_type tellg()
• Returns current position of get pointer
• pos_type tellp()
• Returns current position of put pointer
101
C++ File I/O (Unformatted Binary) Random Access
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
fstream myFile("test.txt", ios::in |
ios::out | ios::trunc); long position;
fstream file;
myFile << "Hello World";
file.open("myfile.txt");
myFile.seekg(6, ios::beg);
file.write("this is an apple", 16);
char A[6]; position = file.tellp();
myFile.read(A, 5);
A[5] = '\0'; file.seekp(position - 7);
file.write(" sam", 4);
cout << A << endl; file.close();
}
myFile.close();
} 102
C++ File I/O: Status Checking
• C++ I/O System maintains status information about the outcome of each
I/O operation
• The current status of an I/O stream is described in an object of type iostate,
which is an enumeration defined in ios with the following values:
• ios::goodbit
• ios::eofbit
• ios::failbit
• ios::badbit
• To read the I/O status you can use rdstate() function
• iostate rdstate()
• It is a member of ios and inherited by all the streams
103
C++ File I/O: Status Checking
#include <iostream> void checkstatus(ifstream &in)
#include <fstream> {
#include <cstdlib> ios::iostate s;
using namespace std; s = in.rdstate();
void checkstatus(ifstream &in); if (s & ios::eofbit)
int main(){ cout <<"EOF encountered" << endl;
char ch; else if (s & ios::failbit)
ifstream in("myfile.txt"); cout<<"Non - Fatal I / O error encountered"<<endl;
if (!in.is_open()){ else if (s & ios::badbit)
cout << "Cannot open file" << endl; cout <<"Fatal I / O error encountered" << endl;
exit(1); }
}
while (!in.eof()){
ch = in.get();
checkstatus(in);
cout << ch;
}
• bool good()
• bool fail()
• bool bad()
105
C++ File I/O: Status Checking
while (!in.eof())
{
ch = in.get();
if (in.fail() || in.bad())
{
cout <<“I / O Error … terminating” << endl;
return 1;
}
cout << ch;
}
106
C++
Miscellaneous Topics
Static Members
108
Static Member
• A data member that is declared static is shared by all
instances of that class and is uniquely stored in one place.
• Non-static data members are created for each instance of
the class.
• A static member (function or variable) can be accessed in the
form -- class_name::member, provided it has public visibility
instead of using its instance or object
• Without static data member, data that was required by all
instances of a class would have to be global.
109
Static Member Variables
• The same static member variable will be used by any classes
derived from the class that contains the static variable
• A static member variable in a sense exists before any object of
its class is created
• Declaration of a static member is not enough; you must define
it outside the class. To do this you must re-declare the static
variable.
• All static member variables are initialized to 0 by default.
110
Static Member Variable (Syntax)
Declaration of
Static Variable
class StaticTest{ main(){
static int i; StaticTest s1,s2;
public: s1.seti(30);
void seti (int n){i=n;} cout<< s2.geti();
int geti(){return i;} }
} Definition of
Static Variable
int StaticTest::i;
111
Static Member Data in Memory
c1 c2 c3
data1
data1
data1 data2
class c { … }; data2
data2
data1
data2 data3
static data3 data4
static data4
112
Static Member Functions
• A static member function can have access to only other static
members (functions or variables). Off course it can access global
data & functions.
• A Static member function does not have a this pointer
• Virtual is not allowed
• Can not be declared as const or volatile
• Can be invoked by any object of its class or can be called
independent of any object via class name and the scope
resolution operator.
113
Static Member Functions
#include <iostream> int main()
using namespace std; {
StaticTest s1, s2;
class StaticTest s1.seti(30);
{ cout << s2.geti()<<endl;
static int i; cout << s1.getVal()<<endl;
cout<<StaticTest::getVal()<<endl;
public: return 0;
void seti(int n) { i = n; } }
int geti() { return i; }
static int getVal(){return i;}
};
int StaticTest::i;
114
Conversion Function
115
User-defined Type conversions
• A conversion operator can be used to convert an object of one
class into
• an object of another class
• a built-in type
• Syntax
operator type() { return a ‘type’ value}
• Return type is the name of the function
116
Conversion Example
class String{
char *str;
public: void main(){
Default Constructor String(){… … …} String str1("Hello");
String (char *s){ String str2="Bye";
int len=strlen(s); String str3=str1;
Conversion Constructor
str=new char[len+1]; str3=“Hello”;
strcpy(str,s);
char* p= str3;
}
strcpy(p,str3);
String (const String &st){
Copy Constructor
int len=strlen(st.str);
str=new char[len+1];
strcpy(str,st.str);
}
Overloaded = operator operator=(char* p){… ... …}
Conversion operator operator char*(){return str;}
}; 117
Namespaces
118
Namespaces
• Namespaces allows same name to be used in different
context
• Localizes the visibility of names declared within it
• Syntax:
namespace name{
//declarations
}
119
Example
using namespace std;
namespace myNS1{
main(){
int i=10;
………
cout<< myNS1::i;
} cout<<myNS2::i;
namespace myNS2{ }
int i=20; main(){
……… std::cout<< myNS1::i;
} std::cout<<myNS2::i;
}
120
Rules and Restrictions
• Namespaces must be declared outside of all other scopes
• ‘using namespace’ is only valid in the box where it is declared
• Namespaces can be nested with one another
• Namespaces can be split files or within a single file
• Unnamed namespaces allows to create identifiers that are
unique within a file
121
Thank You
122