C++ Standard Library Overview and Usage
C++ Standard Library Overview and Usage
Answer: don’t!!!
Overview use the C++ Standard Library.
Standard C++ Library Heart of the library: STL
Concepts
&
Examples
1 2
Containers
Iterators to “run through” the containers vector set/multiset
Algorithms that work on containers:
find, sort, etc.
container adapters: stack, queue, deque
priority_queue map/multimap
iterator adapters list
strings
3 4
1
STL Containers containers include
5 6
7 8
2
C++ strings are containers:
better than C strings
Iterators
9 10
3
Algorithms STL and OO
4
Some algorithms & ranges Efficiency of vector search
list<int> mylist, secondlist;
vector<int> vec;
for (int I = 0; I < 100; ++I) mylist.push_back(I); Let’s search a vector using 3 difference
approaches
list<int>::const_iterator ptr = for each, take the average of 100 searches
find([Link](), [Link](), 99); execute on Gateway x86 laptop, 1GHz
processor, 160 mg RAM
cout << *max_element([Link](), [Link]());
Running RedHat linux 7.1
if ( equal([Link](), [Link](), [Link]()) ) { gcc 2.96
…
}
copy( [Link], [Link](), // source
[Link]() ); // destination 17 18
5
Timing results More efficiency: value vs const/ref
int my_locate(const vector<int> & vec) {
for (int i = 0; i < [Link](); ++i) {
O3 O0 if (vec[i] == 99 ) return vec[i];
my_locate 27.1 148.5 }
iterator_locate 26.4 51.5 return 0;
find 17 34.6 }
23 24
6
Iterator adapters Insert iterator
Iterators are pure abstractions Inserters allow algorithms to operate in
anything that behaves like an iterator, is an insert mode, rather than overwrite mode
iterator
can write classes that have interface of solve a problem: allow algorithms to
iterators but do something different write to a destination that doesn’t have
STL provides several predefined iterators: enough room – grow the destination
insert iterators
stream iterators
three kinds that insert – at front, at end,
reverse iterators or at a given location
25 26
int main() {
list<int>
vector<int>
mylist;
vec;
How predefined inserters work
deque<int> deck;
set<int> myset;
back_inserter is like push_back() – only
for (int I = 1; I <= 10; ++I) { makes sense if container defines it
mylist.push_back(I); front_inserter is like push_front() -- note that
} this reverses the order of inserted items – only
copy([Link](), [Link](), // source
back_inserter(vec) ); // destination
makes sense if container defines push_front
copy([Link](), [Link](), // source inserter calls insert() member function with the
front_inserter(deck); // destination new value and the position (for associative
copy([Link](), [Link](), // source containers the position is a hint to start
inserter(myset, [Link]() )) // destination
search)
}
27 28
7
Stream iterators What does this code do?
int main() {
read from and write to a stream vector<string> vec;
a stream is an object that represents I/O copy ( istream_iterator<string>(cin), // start of source
istream_iterator<string>(), // end of source
channels back_inserter(vec) ); // destination
lets input from keyboard behave as a
sort( [Link](), [Link]() );
collection, from which you can read
can redirect output to a file or screen unique_copy([Link](), [Link](), // source
ostream_iterator<string>(cout, “\n”) ); // destination
}
29 30
8
This code has a memory leak
vector<Student *> vec;
vec.push_back( new Student(“Anakin”) );
Function objects
[Link]( [Link]() );
sorting and searching
when it ain’t easy,
like with pointers
33 34
35 36
9
#include <vector>
#include <algorithm>
Advantages of function object class Less50 {
public:
Less50() { cout << “default” << endl; }
bool operator() (int x) const { return x < 50; }
can have state };
has its own type – can be passed to a vector<int>::const_iterator find_if(const vector<int> & v, const Less50 obj) {
vector<int>::const_iterator ptr = [Link]();
template while (ptr != [Link]() ) { if (obj(*ptr)) return ptr; ++ptr; }
return ptr;
Usually faster than a function pointer }
to see how they work, let’s write our own void fill(vector<int> & n) { }
find_if! int main() {
vector<int> items; fill(items);
vector<int>::const_iterator ptr = find_if(vec, Less50() );
if ( ptr != [Link]() ) cout << “Yes” << endl; else cout << “No” << endl;
37 } 38
#include <vector>
#include <algorithm>
Function objects can have state
class Less50 {
public: can store local values
bool operator() (int x) const { return x < 50; }
}; can provide auxiliary functions
void find_less50(const vector<int> & v) {
assume the following function:
vector<int>::const_iterator ptr = find_if([Link](), [Link](), Less50() ); template <class T>
if (ptr != [Link]() ) cout << the first value < 50 is: “ << *ptr << endl; inline void PRINT_ELEMENTS(const T &coll,
} const char * optcstr="") {
typename T::const_iterator pos;
void fill(vector<int> & n) { } std::cout << optcstr;
for (pos = [Link](); pos != [Link](); ++pos) {
int main() { std::cout << *pos << ' ';
vector<int> items; fill(items); }
find_less50(items); std::cout << std::endl;
} 39 } 40
10
class AddValue { #include <vector>
public: #include <algorithm>
AddValue(int v) : theValue(v) {} class Student {
void operator() ( int &elem) const {
public:
elem += theValue;
} string getName() const { return name; }
private: private:
int theValue; string name;
}; };
class StudentLess {
int main() {
list<int> coll; public:
for (int i = 0; i < 10; ++i) coll.push_back(i); bool operator()(const Student * left, const Student * right) const {
PRINT_ELEMENTS(coll, "Initial values: "); return left->getName() < right->getName();
for_each( [Link](), [Link](), AddValue(10) ); };
PRINT_ELEMENTS(coll, "Values after adding 10: ");
int main() {
for_each([Link](), [Link](),
AddValue(*[Link]())); vector<Student*> items;
PRINT_ELEMENTS(coll, "Values plus first value: "); sort([Link](), [Link](), Less() );
} 41
} 42
#include <vector>
#include <algorithm>
class Student { Using the saved state
public:
string getName() const { return name; }
private: int main() {
string name; vector<Student *> vec;
}; // fill the vector;
class StudentEqual { StudentEqual ob(“Mary”);
public: vector<Student *>const_iterator ptr =
StudentEqual(const string & n) : name(n) {} find_if([Link](), [Link](), ob);
bool operator()(const Student * left, const Student * right) const { if (ptr != [Link]() ) {
return name == right->getName(); cout << *(*ptr) << endl;
} }
private: }
string name;
}; 43 44
11
Standard library exercises
Design an experiment to show
binary_search faster than find
write a program that inserts some items Namespaces
into a vector and prints the list sorted by
name (use a fn obj)
Used by Standard C++ Library
extend your items program to find a
name read from the terminal
extend to read the items from a file
45 46
12
argument dependent name lookup C++ Standard library -- std
All identifiers are in namespace std
Functions don’t have to be qualified if Some compilers enforce use of std
one or more arguments are from the namespace
namespace
gcc’s C++ compiler does not enforce std
NS::Student stu;
until 3.0.4
print(stu);
cout << stu << end;
std::cout << std::hex << 3.4 << std::endl;
49 50
51 52
13
A vector is a block of data with sub-
blocks of size type for vector<type>:
53 54
55 56
14
random access of items:
use array notation: array notation with vectors:
familiar
only way to access non-sequentially
but, library algorithms use iterators
iterators can be written to work on any
container – can then switch if necessary
57 58
59 60
15
size/capacity Reserve
size() – returns actual number in Can avoid capacity doubling if I know how
container much room I will need:
63 64
16
comparing deque and vector
operations
17
iterator invalidation list: inserting & removing
[Link](pos, elem); inserts at iterator position pos,
in general, iterators that refer to a copy of elem, and returns the
container elements are valid as long as position of the new element
the elements stay in the same place!
c.push_back(elem); appends a copy of elem at end
operations can cause elements to move
if insertion causes a vector to grow, then c.pop_back(); removes last element (void fn)
a previously defined iterator is invalid [Link](pos); removes the element at iterator
in contrast, a list iterator never becomes position pos and returns the
invalid as long as elements exist position of the next element
overview
18
three ways
(key, value) pair to insert (key, value) pair
if pos is an iterator pointing to an item in in maps and multimaps, the key is constant
the map: must either provide the correct type or provide
pos->first yields the key of the item implicit or explicit type conversion
pos->second yields the value three ways:
make_pair() – makes a pair that contains 2 values
passed
pair()
value_type()
73 74
#include <map>
19
#include <map>
class Test {
public:
Test(int n) : number(n) {}
int get() const { return number; }
private:
};
int number;
C++ Strings
int main() {
map<Test *, int> my_map;
Test * t = new Test(8);
easier and safer
pair<Test *, int> new_entry(t, 3);
my_map.insert(new_entry); than C-Strings
my_map.insert(make_pair(new Test(99), 2));
map<Test *, int>::const_iterator ptr = my_map.find(t);
if ( ptr != my_map.end() ) cout << ptr->second << endl;
print( my_map );
} 77 78
cin >> s and getline( cin, s ) Note the difference between the following:
these are very different!
string line;
Concatenation, relops all defined fstream input;
input >> line;
getline(input, line);
79 80
20
Sub strings find_first_of()
There are lots of search functions for strings in the library string numerics(“0123456789”);
string name(“r2d2”);
find() is the most straightforward. Given a string:
-- it returns the index of the first character of string::size_type pos = name.find_first_of(numerics);
the matching substring, or if (pos == string::npos) cout << “not found”
-- it returns special value string::npos else cout << “found numeric at: “
<< pos << endl;
string name(“AnnaBelle”);
int pos = [Link](“Anna”); there are two versions of find_first_of
if (pos == string::npos) cout << “not found”
else cout << “found”;
the return type of find is int or string::size_type
81 82
find_first_of substrings
string a(“catalog”);
cout << [Link](0, 3) << endl;
83 84
21
insertion into a string erasing substrings
insert(position, string); several forms:
erase(position);
string state(“Missisippi”); erase(start, how_many);
string::size_type pos = [Link](“isi”);
[Link](pos+1, “s”);
string apple(“apple”);
[Link]([Link](), “s”);
85 86
87 88
22
Web resources:
89 90
#include <iostream>
#include <iostream> #include <vector>
#include <vector> const int MAX = 1024;
const int MAX = 1024; void print(const vector<int> & n) {
vector<int>::const_iterator ptr = [Link]();
void print(const vector<int> & n) { while (ptr != [Link]() ) {
for (int i = 0; i < [Link](); ++i) cout << n[i] << endl; cout << *ptr << endl;
} ++ptr;
}
int main() { }
vector<int> items;
cout << “size of items is: “ << [Link]() << endl; void fill(vector<int> & n) {
items.push_back(rand() % 100); for (int i = 0; i < MAX; ++i) n.push_back(rand()%100);
cout << “size of items is: “ << [Link]() << endl; }
for (int i = 0; i < MAX; ++i) int main() {
items.push_back(rand() %100); vector<int> items;
cout << “size of items is: “ << [Link]() << endl; fill(items); fill(items);
print(items); cout << “size of items is: “ << [Link]() << endl;
} 91 print(items); 92
}
23
#include <iostream>
#include <vector>
#include <iostream>
const int MAX = 1024;
#include <vector>
const int MAX = 1024;
void print(const vector<int> & n) {
vector<int>::const_iterator ptr = [Link]();
void print(const vector<int> & n) {
while ( ptr != [Link]() ) cout << *ptr++ << endl;
vector<int>::const_iterator ptr = [Link]();
}
while ( ptr != [Link]() ) cout << *ptr++ << endl;
} void fill(vector<int> & n) {
for (int i = 0; i < MAX; ++i) n.push_back(rand()%100);
void fill(vector<int> & n) { }
for (int i = 0; i < MAX; ++i) n.push_back(rand()%100);
} int main() {
vector<int> items; Need an iterator to erase an item
int main() { fill(items);
vector<int> items; vector<int>::iterator ptr = [Link]();
fill(items); fill(items); ++ptr;
cout << “size of items is: “ << [Link]() << endl; [Link](ptr);
print(items); cout << “size of items is: “ << [Link]() << endl;
} 93 print(items); 94
}
24
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
const int MAX = 10; const int MAX = 10;
void locate(const vector<int> & v, int x) { void locate(const vector<int> & v, int x) {
vector<int>::const_iterator ptr = find( [Link](), [Link](), x ); if ( binary_search( [Link](), [Link](), x ) ) cout << x << “ found\n”;
if (ptr == [Link]() ) cout << x << “ not found” << endl; else cout << x << “ not found“ << endl;
else cout << x << “ found at location: “ << [Link]() << endl; }
}
int main() {
int main() { vector<int> items;
vector<int> items; fill(items);
fill(items); sort( [Link](), [Link]() );
locate(items, 99); locate(items, 99);
print(items); print(items);
} 97
} 98
25
Ordinary use: use reserve():
101 102
103 104
26
sort of sequential containers can be easy
#include <vector>
#include <iostream>
#include <algorithm>
algorithms int main() {
vector<int> vec;
sorting and searching for (int I = 0; I < MAX; ++I) vec.push_back(rand() % 100);
sort([Link](), [Link]());
sequential containers }
sort works for any item that has <
defined for it.
105 106
#include <vector>
#include <algorithm> Sorting list
class Student {
public:
string getName() const { return name; } A list is not a random access container
bool operator<(const Student & rhs) const {
return name < [Link](); must use sort routine in list
}
private:
string name;
};
int main() {
vector<Student> items;
sort([Link](), [Link]() );
} 107 108
27
#include <iostream>
#include <list>
const int MAX = 1024; find can be easy
void print(const list<int> & n) {
list<int>::const_iterator ptr = [Link](); #include <vector>
while (ptr != [Link]() ) cout << *ptr++ << endl; #include <iostream>
} #include <algorithm>
void fill(list<int> & n) {
for (int i = 0; i < MAX; ++i) n.push_back(rand()%100);
int main() {
}
vector<int> vec;
int main() { for (int I = 0; I < MAX; ++I) vec.push_back(rand() % 100);
list<int> items; vector<int>::const_iterator ptr =
fill(items); fill(items); find([Link](), [Link](), 99);
[Link](); }
print(items);
}
find works for any item that has ==
defined for it.
109 110
28