and more... The standard library is the collection of functions and - - PowerPoint PPT Presentation

and more
SMART_READER_LITE
LIVE PREVIEW

and more... The standard library is the collection of functions and - - PowerPoint PPT Presentation

Containers, algorithms and more... The standard library is the collection of functions and types that is supplied with every standard-compliant C++ compiler What should be in the standard library? And equally important: what should not


slide-1
SLIDE 1

Containers, algorithms and more...

slide-2
SLIDE 2

 The standard library is the collection of

functions and types that is supplied with every standard-compliant C++ compiler

 What should be in the standard library?

 And equally important: what should not be?

Introduction to Systems Programming 2

slide-3
SLIDE 3

 The standard library should:

 Provide basic functionality which the user can

have difficulty implementing himself:

 Memory management  Input / output  Implementation-dependent information

 Save and simplify work:

 Supply useful non-primitive facilities

Introduction to Systems Programming 3

slide-4
SLIDE 4

 The standard library cannot contain problem-

specific code

 For example – a Student class

 It should contain generic classes and functions

which are usable in a variety of problems:

 Containers – such as list, set, etc.  Algorithms – such as sorting, searching  Popular classes – such as string

Introduction to Systems Programming 4

slide-5
SLIDE 5

 What are the requirements from the standard library's

containers and algorithms?

 Simple to use

 Interfaces should be uniform and convenient

 Complete

 Reasonable features should be included

 Efficient

 Library code might take a large part of the execution time

 Extensible

 The user should be able to add new containers and algorithms that work with the given ones

Introduction to Systems Programming 5

slide-6
SLIDE 6

 The containers included in the standard library should

be generic

 We have seen several ways to implement generic

containers:

 Using void* and pointers to functions  Using templates  Using subtyping and polymorphism

Introduction to Systems Programming 6

slide-7
SLIDE 7

 The standard template library (STL) is a collection of

containers and algorithms which is part of the standard C++ library

 Makes heavy use of C++ templates

 And many interesting and advanced programming

techniques

 Developed by Alexander Stepanov and Meng Lee at HP

Introduction to Systems Programming 7

slide-8
SLIDE 8

 The STL includes several generic containers:

Introduction to Systems Programming 8

vector deque array list forward_list Sequence Containers stack queue priority_queue Adaptors set map multiset multimap Associative Containers unordered_set unordered_map unordered_multiset unordered_multimap Unordered Associative Containers

slide-9
SLIDE 9

The most commonly used container is std::vector

 Defined in the standard header <vector>

Essentially, a vector is a dynamic array

 Elements are sequential in memory  Fast random access to elements by index  Insertion and removal of elements at the end of the vector is fast

 Due to pre-allocation of memory

 Insertion and removal elsewhere in the vector may be very slow

Introduction to Systems Programming 9

void read_and_print() { vector<int> numbers; int input; while (cin >> input) { numbers.push_back(input); } for (int n : numbers) { cout << n << " "; } }

slide-10
SLIDE 10

 Vector has a large selection of constructors,

some of which are:

Introduction to Systems Programming 10

vector<int> v1; vector<double> v2(10, 1.0); vector<double> v3(10); vector<double> v4(v2); vector<string> words = { "Hello", "World" }; int array[] = { 1, 2, 3 }; vector<int> v5(array, array + 3); vector<int> v6(v2.begin(), v2.end());

slide-11
SLIDE 11

 Vectors have random access like arrays:

 operator[] can be used to access elements without any run-time

check of the index (result is undefined if the index is invalid!)

 The member function at() provides a safer (but slower) version

  • f operator[], which throws an exception if the index is illegal

Introduction to Systems Programming 11

vector<string> words = { "Hello", "World" }; for (unsigned i = 0; i < words.size(); ++i) { cout << words[i] << endl; } try { cout << words.at(2) << endl; } catch (const std::out_of_range& e) { cerr << e.what() << endl; }

slide-12
SLIDE 12

 Elements can be efficiently inserted and removed from the

end of a vector

 Elements can also be inserted and erased from any place in

the vector, though inefficiently

Introduction to Systems Programming 12

vector<string> words = { "Hello", "World" }; vector<string>::iterator i = words.begin(); words.insert(++i, "Lovely"); words.erase(words.begin()); vector<string> words = { "Hello", "World" }; words.push_back("!!!"); words.pop_back();

slide-13
SLIDE 13

 Elements placed into a vector must be “copy

constructible” and “assignable”

 So a working copy c’tor and operator= are required  A default c’tor is not required

 When dealing with a polymorphic base class, use

shared_ptr to store the elements in the vector

 This will save you from the need to explicitly delete

elements before removing them from the vector

Introduction to Systems Programming 13

slide-14
SLIDE 14

 There is more to vector's interface – look online

 This is true for all containers

 Some things that were not discussed:

 Vectors have methods to allow fine control over the memory

they use (e.g., resizing, preallocation)

 Vectors, like other containers, have an optional template

argument called Allocator

 Allocators allow the user to control how and where new elements are allocated – this is important for efficiency reasons  We will ignore them in our survey of the STL

Introduction to Systems Programming 14

slide-15
SLIDE 15

The rest of the containers behave similarly to vector

 So no need to go over them thoroughly

The container std::deque (short for "Double Ended Queue") is like a vector, but allows fast insertion and removal from its beginning as well

 Using the push_front() and pop_front() methods

The container std::array is a constant-size array

 Size must be known at compilation time  Basically wraps a C-style array

Introduction to Systems Programming 15

deque<string> words = { "Hello", "World" }; words.pop_front(); words.push_front("Hi"); array<string, 2> words = { "Hello", "World" }; words.at(0) = "Hi"; cout << words.at(3) << endl;

slide-16
SLIDE 16

The container std::list is implemented as a doubly-linked list

 There are no methods for random (index-based) access  There is support for fast merging and splicing of lists

The container std::forward_list is a singly-linked list with pointers from each node only to the next one

 Takes less memory  But has a slimmer interface, e.g., no operator--() for iterators

Introduction to Systems Programming 16

list<string> words = { "Hello", "World" }; list<string> words2 = { "Lovely" }; words.splice(++words.begin(), words2); forward_list<string> words = { "Hello", "World" }; forward_list<string> words2 = { "Lovely" }; words.splice_after(words.begin(), words2);

slide-17
SLIDE 17

 Unlike sequence containers, associative containers

do not provide control over element order

 The order of iteration is unrelated to the order of insertion

 Example: set is an associative container

Introduction to Systems Programming 17

set<int> numbers; for (int n : { 1, 3, 2, 3 }) { numbers.insert(n); } for (int n : numbers) { cout << n << endl; }

slide-18
SLIDE 18

 Set stores its elements in sorted order

 By default, set compares elements using operator<()  This is usually bad when using pointers

Introduction to Systems Programming 18

set<Employee*> employees; employees.insert(new Employee("John")); employees.insert(new Employee("Jill")); employees.insert(new Employee("John")); for (const Employee* e : employees) { cout << e->getName() << endl; } class Employee { string name; public: Employee(string name) : name(name) {} string getName() const { return name; } // ... };

slide-19
SLIDE 19

The comparison function is passed to set as a template argument

 We can replace the default operator<() with a function object

Introduction to Systems Programming 19

set<Employee*, CompareByName> employees; employees.insert(new Employee("John")); employees.insert(new Employee("Jill")); employees.insert(new Employee("John")); for (const Employee* e : employees) { cout << e->getName() << endl; } class Employee { string name; public: Employee(string name) : name(name) {} string getName() const { return name; } // ... }; class CompareByName { public: bool operator()(const Employee* e1, const Employee* e2) const { return e1->getName() < e2->getName(); } };

slide-20
SLIDE 20

 Another associative container is map

 A map stores pairs of (key, value)  The keys are unique (only one of each)  Map is basically a set, with extra information stored

for each element

Introduction to Systems Programming 20

map<int, string> idToName; idToName[123456789] = "John"; idToName[987654321] = "Jill"; idToName[123454321] = "John"; idToName[123454321] = "Jill"; for (const pair<int,string>& idNamePair : idToName) { cout << idNamePair.first << ": " << idNamePair.second << endl; }

slide-21
SLIDE 21

void most_frequent_word() { string word; map<string, int> count; while (cin >> word) { count[word]++; } string max_word; int max_count = 0; for (const pair<string,int>& p : count) { if (p.second > max_count) { max_word = p.first; max_count = p.second; } } cout << max_word << endl; }

Introduction to Systems Programming 21

slide-22
SLIDE 22

 The STL supplies multiset and multimap which allow

storing the same key multiple times

 In addition, C++11 adds unordered_set, unordered_map,

unordered_multiset and unordered_multimap

 These containers use a hash-table implementation instead of a

binary tree

Introduction to Systems Programming 22

slide-23
SLIDE 23

Adaptors are container wrappers which limit or modify the existing container's interface

 For example, stack or queue  Why would we want to limit an interface?

Adaptors take a container as an additional template argument

 Allowing the user to choose the implementation of his

stack/queue/priority queue

 They adapt the sequence container to a specific, simple usage

Introduction to Systems Programming 23

stack<int> stack1; stack<int, list<int>> stack2; for (int n : { 2, 1, 3 }) { stack1.push(n); } while (!stack1.empty()) { stack2.push(stack1.top()); stack1.pop(); }

slide-24
SLIDE 24

Introduction to Systems Programming 24

int main() { stack<int> numbers; for (int n : { 2, 1, 3 }) { numbers.push(n); } while (!numbers.empty()) { cout << numbers.top(); cout << " "; numbers.pop(); } return 0; } int main() { queue<int> numbers; for (int n : { 2, 1, 3 }) { numbers.push(n); } while (!numbers.empty()) { cout << numbers.front(); cout << " "; numbers.pop(); } return 0; } int main() { priority_queue<int> numbers; for (int n : { 2, 1, 3 }) { numbers.push(n); } while (!numbers.empty()) { cout << numbers.top(); cout << " "; numbers.pop(); } return 0; }

slide-25
SLIDE 25

 Don’t feel confused by the large number of

different containers

 If you don't know which to use, go with vector  In time, the differences will become clearer

 How each of these containers can be

implemented efficiently is taught in Data Structures 1 (234218)

Introduction to Systems Programming 25

slide-26
SLIDE 26

 A common feature of most containers is iterators  This enables writing generic algorithms that work

with several containers

Introduction to Systems Programming 26

template<class InputIterator, class OutputIterator> OutputIterator copy(InputIterator first, InputIterator last, OutputIterator target) { while (first != last) *(target++) = *(first++); return target; } set<int> numbers; // ... vector<int> v(numbers.size()); copy(numbers.begin(), numbers.end(), v.begin());

slide-27
SLIDE 27

 Iterators are a concept – there is no class “iterator”

 A concept is essentially a set of requirement imposed on a

template argument

 Many classes can be iterators, as long as they support the

required operations

 The STL recognizes five categories of iterators:

Introduction to Systems Programming 27

slide-28
SLIDE 28

 A forward iterator supports the following 3 operations:

 Advancing the iterator with ++i and i++  Operator* for dereferencing (retrieving the current element)  Comparison with == and !=

Introduction to Systems Programming 28

forward_list<int> numbers = { 1, 2, 3, 4 }; forward_list<int>::iterator i = numbers.begin(); while (i != numbers.end()) { *i = 2 * (*i); ++i; }

slide-29
SLIDE 29

 A bi-directional iterator adds support for decrementing

the iterator

 Supports --i and i--  Supports all of the forward iterator's operations  std::list provides bi-directional iterators

Introduction to Systems Programming 29

list<int> numbers = { 1, 2, 3, 4 }; list<int>::iterator i = numbers.end(); while (i != numbers.begin()) {

  • -i;

cout << *i << endl; }

slide-30
SLIDE 30

A random access iterator supports:

 Anything that can be done with a bi-directional iterator  Comparison through operators <, <=, > and >=  Moving forward or backward by n elements in the container with + or -  Calculating the distance between two iterators with -  Random access using operator[]

A pointer is a random access iterator for a C-style array

std::vector provides a random access iterator

Introduction to Systems Programming 30

vector<int> numbers = { 1, 2, 3, 4, 5, 6, 7, 8 }; vector<int>::iterator i = numbers.begin(); while (i < numbers.end()) { cout << *i << endl; i += 3; }

slide-31
SLIDE 31

 An output iterator supports the same operations as a

forward iterator with one important difference:

 The dereferenced element (via operator*) can only be

written to, and only once

 The range of elements may only be iterated once

 We can get such an iterator for an ostream object:

Introduction to Systems Programming 31

  • stream_iterator<int> out (cout, ", ");

int n; while (cin >> n) { *(out++) = n; }

slide-32
SLIDE 32

 An input iterator is similar to an output iterator, but this

time the referenced element can only be read from

 Again, you may only do a single pass on the range of elements

Introduction to Systems Programming 32

map<string, int> count; ifstream fin("words.txt"); istream_iterator<string> end; for (istream_iterator<string> i(fin); i != end; ++i) { count[*i]++; }

slide-33
SLIDE 33

 We can now use the different iterator categories to

describe the requirements of generic algorithms

Introduction to Systems Programming 33

template<class InputIterator, class OutputIterator> OutputIterator copy(InputIterator first, InputIterator last, OutputIterator target) { while (first != last) *(target++) = *(first++); return result; } ifstream fin("words.txt");

  • fstream fout("output.txt");

copy(istream_iterator<string>(fin), istream_iterator<string>(),

  • stream_iterator<string>(fout, " "));
slide-34
SLIDE 34

The STL comes with the <algorithm> header which contains a variety of common algorithms

 All these algorithms operate on iterators, not on specific containers  Combining these algorithms with the containers gives a powerful

standard library

 Users can create new containers and new algorithms that can be

combined with the STL by simply following the same conventions

Introduction to Systems Programming 34

bool is_anagram(string str1, string str2) { sort(str1.begin(), str1.end()); sort(str2.begin(), str2.end()); return str1 == str2; } cout << is_anagram("dog", "god"); cout << is_anagram("no", "way");

slide-35
SLIDE 35

 Count the number of words in a string:

Introduction to Systems Programming 35

int count_words(string str) { istringstream is(str); istream_iterator<string> start(is); istream_iterator<string> end; return std::distance(start, end); } string str("The quick brown fox jumps\n" " over the lazy dog"); cout << count_words(str) << endl;

slide-36
SLIDE 36

 Erase values from a vector according to a given

condition, and print its contents:

Introduction to Systems Programming 36

vector<double> numbers = { -1.0, 0.33, -0.44, 2.5 }; vector<double>::iterator i = remove_if(numbers.begin(), numbers.end(), is_negative); numbers.erase(i, numbers.end()); copy(numbers.begin(), numbers.end(), ostream_iterator<double>(cout, ", ")); bool is_negative(double d) {

return d < 0; }

slide-37
SLIDE 37

 The STL supplies a set of useful tools for programming in C++

 Use it whenever possible instead of reinventing the wheel

 Don’t expect to remember it by heart – it’s too big

 Look online for resources, usually what you need already exists  There's much more to it, but outside the scope of this course

 There are many containers, but in many cases there is no

need to optimize anything:

 If you don’t know what you need – use a vector

Introduction to Systems Programming 37

slide-38
SLIDE 38

“The bearing of a child takes nine months, no matter how many women are assigned. Many software tasks have this characteristic because of the sequential nature of debugging.”

  • Fred Brooks

Introduction to Systems Programming 38