C++ Standard Template Library. Contents. Pierre Fierz. 1 Introduction. 2 Organization of STL Header Files. Organization of STL Header Files

Similar documents
STL: C++ Standard Library

Template based set of collection classes STL collection types (container types)

Chapter 5. The Standard Template Library.

Lecture 21 Standard Template Library. A simple, but very limited, view of STL is the generality that using template functions provides.

Standard Library Reference

Container Notes. Di erent Kinds of Containers. Types Defined by Containers. C++11 Container Notes C++11

Standard Template Library

Lecture-5. STL Containers & Iterators

Object-Oriented Programming for Scientific Computing

SSE2034: System Software Experiment 3

Purpose of Review. Review some basic C++ Familiarize us with Weiss s style Introduce specific constructs useful for implementing data structures

Programming in C++ using STL. Rex Jaeschke

CS11 Advanced C++ Fall Lecture 1

Unit 1: Preliminaries Part 4: Introduction to the Standard Template Library

19.1 The Standard Template Library

STL components. STL: C++ Standard Library Standard Template Library (STL) Main Ideas. Components. Encapsulates complex data structures and algorithms

CS197c: Programming in C++

Containers in C++ and Java

Today. andyoucanalsoconsultchapters6amd7inthetextbook. cis15-fall2007-parsons-lectvii.1 2

CSCI-1200 Data Structures Fall 2017 Lecture 9 Iterators & STL Lists

Exceptions, Templates, and the STL

Programming with Haiku

Templates and Vectors

Sets and MultiSets. Contents. Steven J. Zeil. July 19, Overview of Sets and Maps 4

MODULE 33 --THE STL-- ALGORITHM PART I

Associative Containers and Iterators. Ali Malik

The Standard Template Library Classes

THE STANDARD TEMPLATE LIBRARY (STL) Week 6 BITE 1513 Computer Game Programming

by Pearson Education, Inc. All Rights Reserved. 2

CSCI-1200 Data Structures Fall 2014 Lecture 8 Iterators

CSCI-1200 Data Structures Fall 2010 Lecture 8 Iterators

COEN244: Class & function templates

1. The term STL stands for?

CSCI-1200 Data Structures Fall 2017 Lecture 10 Vector Iterators & Linked Lists

C++ Basics. Data Processing Course, I. Hrivnacova, IPN Orsay

Standard Template Library. Containers, Iterators, Algorithms. Sequence Containers. Containers

use static size for this buffer

CPSC 427a: Object-Oriented Programming

CE221 Programming in C++ Part 2 References and Pointers, Arrays and Strings

Unit 4 Basic Collections

Arrays - Vectors. Arrays: ordered sequence of values of the same type. Structures: named components of various types

Outline. Variables Automatic type inference. Generic programming. Generic programming. Templates Template compilation

To use various types of iterators with the STL algorithms ( ). To use Boolean functions to specify criteria for STL algorithms ( 23.8).

Lecture 10. To use try, throw, and catch Constructors and destructors Standard exception hierarchy new failures

The Standard Template Library. An introduction

Standard Template Library

2

CSCI-1200 Data Structures Spring 2016 Lecture 7 Iterators, STL Lists & Order Notation

Short Notes of CS201

Absolute C++ Walter Savitch

Function Templates. Consider the following function:

GridKa School 2013: Effective Analysis C++ Standard Template Library

Overview. Part II: Containers and Algorithms. Overview. Overview

CS201 - Introduction to Programming Glossary By

STL Quick Reference for CS 241

Lectures 11,12. Online documentation & links

Chapter 15 - C++ As A "Better C"

Polymorphism. Programming in C++ A problem of reuse. Swapping arguments. Session 4 - Genericity, Containers. Code that works for many types.

Introduction to C++ Professor Hugh C. Lauer CS-2303, System Programming Concepts

Type Aliases. Examples: using newtype = existingtype; // C++11 typedef existingtype newtype; // equivalent, still works

C++ 11 and the Standard Library: Containers, Iterators, Algorithms

CSCI-1200 Data Structures Fall 2013 Lecture 9 Iterators & Lists

Pointers and Arrays CS 201. This slide set covers pointers and arrays in C++. You should read Chapter 8 from your Deitel & Deitel book.

CS183 Software Design. Textbooks. Grading Criteria. CS183-Su02-Lecture 1 20 May by Eric A. Durant, Ph.D. 1

Introduction to C++ Systems Programming

15. Pointers, Algorithms, Iterators and Containers II

Class string and String Stream Processing Pearson Education, Inc. All rights reserved.

C++: Overview and Features

C++ Standard Template Library

To know the relationships among containers, iterators, and algorithms ( 22.2).

CSCI-1200 Data Structures Spring 2018 Lecture 10 Vector Iterators & Linked Lists

CSE 100: C++ TEMPLATES AND ITERATORS

Lesson 13 - Vectors Dynamic Data Storage

Summary. Design. Layout

CS11 Advanced C++ Spring 2018 Lecture 2

CSCI-1200 Data Structures Fall 2017 Lecture 5 Pointers, Arrays, & Pointer Arithmetic

CS2255 HOMEWORK #1 Fall 2012

Sequential Containers. Ali Malik

CSCE 206: Structured Programming in C++

CSCE 206: Structured Programming in C++

Standard Template Library. Outline

Interview Questions of C++

Document Number: P0429R4 Date: Reply to: 0.1 Revisions... 1

Prefix Trees Tables in Practice

Chapter 17: Linked Lists

Introduction to C++ Introduction to C++ 1

What will happen if we try to compile, link and run this program? Do you have any comments to the code?

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

7 TEMPLATES AND STL. 7.1 Function Templates

List, Stack, and Queues

Standard Containers Library (1)

COMP322 - Introduction to C++

CSE 100: C++ TEMPLATES AND ITERATORS

Introducing C++ to Java Programmers

C++ 프로그래밍실습. Visual Studio Smart Computing Laboratory

vector<int> second (4,100); // four ints with value 100 vector<int> third (second.begin(),second.end()); // iterating through second

More on Templates. Shahram Rahatlou. Corso di Programmazione++

SETS AND MAPS. Chapter 9

CSCI-1200 Data Structures Fall 2012 Lecture 5 Pointers, Arrays, Pointer Arithmetic

std::string Quick Reference Card Last Revised: August 18, 2013 Copyright 2013 by Peter Chapin

Transcription:

Contents Chapter 3 1 Lecture Advanced C++ 05.03.2012 2 3 4 Associative 5 Associative 6 Bernese University of Applied Sciences School of Engineering and Information Technology Division of Computer Science 7 Associative 3.1 3.2 1 Why should we use the C++ STL? It is better to reuse existing code, then to rewrite it 2 3 4 5 6 Associative The Standard uses two features of C++ that supports data independence: Templates Operator overloading With these features an algorithm can assume just very little about the actual object, which can be: Fundamental data type (int, double, char,...) User-defined data types/classes (String, Complex,...) Consequently,such an algorithm is not confined to a specific data type, and it has a higher reusability potential than does a type-dependent algorithm. Associative 7 Associative The Standard (STL) is an exemplary framework that is built on the foundations of generic programming. 3.3 3.4

(2) STL is a collection of generic algorithms and containers The communication between containers and algorithms is done through iterators STL components are grouped together under the namespace std We have the following groups of STL components: Numeric libraries Utilities String... Associative 1 2 3 4 5 6 7 Associative Associative 3.5 3.6 (2) Container classes are repositories for different kind of data types in different storing ways Header <vector> <list> <deque> <queue> <stack> <map> <multimap> <set> <multiset> <bitset> Contents An array of T A doubly-linked list of T A double-ended queue of T A queue of T A stack of T An associative array of T with unique keys An associative array of T A set of T A bag of T A set of Boolean values Associative STL generic algorithms can be applied to a sequence of elements. They are defined in the following header file. Header <algorithm> Contents A collection of generic algorithms are used to navigate sequences. They are defined in the following header file. Header <iterator> Contents Various types of iterators and iterator support Associative 3.7 3.8

(3) STL provides several classes and algorithms that are specifically designed for numeric computations (see the following table). 1 Header <complex> <valarray> <numerics> Contents Complex numbers and their associated operations Mathematical vectors and their associated operations Generalized numeric operations The headers in the following table define auxiliary components that are used in STL containers and algorithms. These include function adaptors, pairs, and class auto_ptr (discussed later). Associative 2 3 4 5 6 Associative Header <utility> <functional> <memory> Contents Operators and pairs Function objects Allocators and auto_ptr 7 Associative 3.9 3.10 (2): Sequence A container can hold objects A container is not confined to a specific type, it can store objects of any kind In the old C era, the only container is the well known built-in array These built-in array are inherited into C++, the corresponding STL container is the vector which provide random access and can store any type of data Arrays doesn t allow to insert new elements in the middle of the array Furthermore, they don t allow to append elements at the end of the array (fixed size) Other data models (e.g. lists) allow to add elements in the middle or to append new elements at the front or the end Associative A sequence container organizes a collection of objects of the same type T into a strictly linear arrangement. Following are examples of sequence containers: T v[n ] A built-in array that stores a fixed number of n elements and provides random access to them. std::vector<t> An array-like container that stores a varying number of n elements and provides random access to them. Insertions and deletions at the end of a vector are constant time operations. std::deque<t> A double-ended queue that provides random access to a sequence of varying length, with constant time insertions and deletions at the beginning and the end. std::list<t> A list that provides linear time access to a sequence of varying length, with constant time insertions and deletions at any position. Associative 3.11 3.12

(3): Sequence (4): Vector The vector container type is very similar to an array To choose a container, decide what sort of operations you will most frequently perform on your data, then use the following table to help you. Operation vector deque list Access first element Constant Constant Constant Access last element Constant Constant Constant Access random element Constant Constant Linear Add/Delete at beginning Linear Constant Constant Add/Delete at end Constant Constant Constant Add/Delete at random Linear Linear Constant Associative The random access is possible as in normal array. The time overhead for reading is constant (order O(1)) my_vector[2] = 3; a = my_vector[7]; Manipulating (add / delete) at the end of the vector is cheap Bounds are not checked automatically!! Insertions or deletions anywhere not at the end adds a linear time overhead (order O(N), N elements in vector) Shuffling around is necessary Memory overhead is low, comparable to a normal array Associative 3.13 3.14 (5): vector (5): vector The table below shows some of the main vector functions. The table below shows some of the main vector functions. Interface Vector Interface Vector begin() end() Returns iterator pointing to first element Returns iterator pointing after last element push_back(...) Add element to end of vector pop_back(...) Destroy element at end of vector Associative Associative 3.15 3.15

(5): vector (5): vector The table below shows some of the main vector functions. The table below shows some of the main vector functions. Interface Vector Interface Vector push_back(...) Add element to end of vector pop_back(...) Destroy element at end of vector swap(, ) Swap two elements insert(, ) Insert new element Associative push_back(...) Add element to end of vector pop_back(...) Destroy element at end of vector swap(, ) Swap two elements insert(, ) Insert new element size() Number of elements in vector capacity() Capacity before more memory is needed empty() True if vector is empty Associative 3.15 3.15 (5): vector The table below shows some of the main vector functions. Interface Vector push_back(...) Add element to end of vector pop_back(...) Destroy element at end of vector swap(, ) Swap two elements insert(, ) Insert new element size() Number of elements in vector capacity() Capacity before more memory is needed empty() True if vector is empty [] Random access operator at() Random access operator with bound check Associative (6): double-ended queue The double-ended queue, deque has similar properties to a vector Additional feature for adding and deleting elements at both ends Random read access exists like in vector The deque is (like the vector also) not very good at inserting or deleting elements at random positions Associative 3.15 3.16

(6): double-ended queue The double-ended queue, deque has similar properties to a vector Additional feature for adding and deleting elements at both ends Random read access exists like in vector The deque is (like the vector also) not very good at inserting or deleting elements at random positions Interface Double-Ended Queue (6): double-ended queue The double-ended queue, deque has similar properties to a vector Additional feature for adding and deleting elements at both ends Random read access exists like in vector The deque is (like the vector also) not very good at inserting or deleting elements at random positions Interface Double-Ended Queue Associative push_front(...) Add element to front of deque pop_front(...) Destroy element at front of deque Associative 3.16 3.16 (6): double-ended queue The double-ended queue, deque has similar properties to a vector Additional feature for adding and deleting elements at both ends Random read access exists like in vector The deque is (like the vector also) not very good at inserting or deleting elements at random positions Interface Double-Ended Queue (6): double-ended queue The double-ended queue, deque has similar properties to a vector Additional feature for adding and deleting elements at both ends Random read access exists like in vector The deque is (like the vector also) not very good at inserting or deleting elements at random positions Interface Double-Ended Queue push_front(...) Add element to front of deque pop_front(...) Destroy element at front of deque push_back(...) Add element to end of deque pop_back(...) Destroy element at end of deque Associative push_front(...) Add element to front of deque pop_front(...) Destroy element at front of deque push_back(...) Add element to end of deque pop_back(...) Destroy element at end of deque swap(, ) Swap two elements insert(, ) Insert new element Associative 3.16 3.16

(6): double-ended queue The double-ended queue, deque has similar properties to a vector Additional feature for adding and deleting elements at both ends Random read access exists like in vector The deque is (like the vector also) not very good at inserting or deleting elements at random positions Interface Double-Ended Queue (6): double-ended queue The double-ended queue, deque has similar properties to a vector Additional feature for adding and deleting elements at both ends Random read access exists like in vector The deque is (like the vector also) not very good at inserting or deleting elements at random positions Interface Double-Ended Queue push_front(...) Add element to front of deque pop_front(...) Destroy element at front of deque push_back(...) Add element to end of deque pop_back(...) Destroy element at end of deque swap(, ) Swap two elements insert(, ) Insert new element size() Number of elements in deque capacity() Element capacity before more memory needed empty() True if deque is empty Associative 3.16 push_front(...) Add element to front of deque pop_front(...) Destroy element at front of deque push_back(...) Add element to end of deque pop_back(...) Destroy element at end of deque swap(, ) Swap two elements insert(, ) Insert new element size() Number of elements in deque capacity() Element capacity before more memory needed empty() True if deque is empty [] Random access operator at() at() Random access operator with bound check Associative 3.16 (7): List List containers doesn t provide a random access operator (no []) Lists are suited to add or delete elements randomly in the list Implemented as double-linked list structure and support bidirectional iterators (7): List List containers doesn t provide a random access operator (no []) Lists are suited to add or delete elements randomly in the list Implemented as double-linked list structure and support bidirectional iterators Interface List Associative Associative 3.17 3.17

(7): List (7): List List containers doesn t provide a random access operator (no []) Lists are suited to add or delete elements randomly in the list Implemented as double-linked list structure and support bidirectional iterators Interface List List containers doesn t provide a random access operator (no []) Lists are suited to add or delete elements randomly in the list Implemented as double-linked list structure and support bidirectional iterators Interface List push_front(...) Add element to front of list pop_front(...) Destroy element at front of list Associative push_front(...) Add element to front of list pop_front(...) Destroy element at front of list push_back(...) Add element to end of list pop_back(...) Destroy element at end of list Associative 3.17 3.17 (7): List (7): List List containers doesn t provide a random access operator (no []) Lists are suited to add or delete elements randomly in the list Implemented as double-linked list structure and support bidirectional iterators Interface List List containers doesn t provide a random access operator (no []) Lists are suited to add or delete elements randomly in the list Implemented as double-linked list structure and support bidirectional iterators Interface List push_front(...) Add element to front of list pop_front(...) Destroy element at front of list push_back(...) Add element to end of list pop_back(...) Destroy element at end of list swap(, ) Swap two elements erase(...) Delete elements insert(, ) Insert new element Associative push_front(...) Add element to front of list pop_front(...) Destroy element at front of list push_back(...) Add element to end of list pop_back(...) Destroy element at end of list swap(, ) Swap two elements erase(...) Delete elements insert(, ) Insert new element size() Number of elements in list capacity() Element capacity before more memory needed empty() True if list is empty Associative 3.17 3.17

(7): List List containers doesn t provide a random access operator (no []) Lists are suited to add or delete elements randomly in the list Implemented as double-linked list structure and support bidirectional iterators Interface List push_front(...) Add element to front of list pop_front(...) Destroy element at front of list push_back(...) Add element to end of list pop_back(...) Destroy element at end of list swap(, ) Swap two elements erase(...) Delete elements insert(, ) Insert new element size() Number of elements in list capacity() Element capacity before more memory needed empty() True if list is empty sort() Specific function because <algorithm> sort routines expect random access iterators Associative 3.17 (8): Accessing single Elements Two different methods for accessing single elements in vectors and queues exist. The overloaded subscript operator [], or the member function at() for direct access to a vector s element. Both exist in a const and a non-const version The overloaded subscript operator [] Efficient (normally inline) No range check performed (dangerous) The member function at() Less efficient Range check is performed, throws an exception (std::out_of_range) in case of out-of-bound access int main() { using namespace std; vector<string> vs; // vs has no elements currently vs.push_back( "string" ); // add first element vs[0] = "overriding string"; // override it using [] try { cout << vs.at(10) << endl; // exception: out of range catch( std::out_of_range& except ) { // handle out-of-range subscript Associative 3.18 (9): Front and Back Operations Front and back operations refer to the beginning and the end of a container, respectively. The member function push_back() appends a single element to the end of the container. When the it reallocates additional storage, and then appends the element. The member function pop_back() removes the last element from the container. The member functions front() and back() access a single element at the container s beginning and end, respectively. int main() { using namespace std; Associative 1 2 3 4 5 Associative vector<short> v; v.push_back( 5 ); v.push_back( 10 ); cout << "front: " << v.front() << endl; // 5 cout << "back: " << v.back() << endl; // 10 v.pop_back(); // remove v[1], // which is 10 cout << "back: " << v.back() << endl; // now 5 3.19 6 7 Associative 3.20

(2): begin() and end() Every container posseses the two functions begin() and end() An iterator is an abstraction of a pointer to an element of a container. The fundamental concepts of an iterator are: Return the value of the element which it points to (dereferencing represented by the operators * and >) Point to the next element (increment represented by the operator ++) Compare two pointers (represented by the operator ==) The begin() method returns an iterator that points to the first element of a container The end() method returns an iterator that points one position past the last element of the container Can be seen as a pointer to the null-character \0 of a null-terminated string This allows easy usage for looping through a container The datatype int* is an iterator for the datatype int[]. The class list<int>::iterator is an iterator for the class list<int> Associative vector<int> v; int n = 0; for (vector<int>::iterator p = v.begin(); p =! v.end(); p++) { std::cout << *p << std::endl; Associative Const and non-const version of the iterators exist A reverse version of the iterators also exists (rbegin() and rend(), the y return reverse iterators 3.21 3.22 (3): Iterator categories (4): Iterator categories There are five different iterator categories Input permit only read accesses and can only be moved forward sequentially. An element can only be read once. An example is an iterator reading characters from the keyboard. Output permit only write accesses and can only be moved forward sequentially. An example is an iterator writing characters to the standard output. Forward are a combination of input and output iterators. They can only be moved forward sequentially, now however reading and writing are allowed. Bidirectional extends the abilities of the forward by the possibility to be moved backward sequentially. Random Access are the most flexible iterators. They cannot only be moved sequentially, they also permits a direct access to any position in a given range. Associative 3.23 The following table shows, which operators are implemented for the different iterator categories. Iterator operators output input forward bidirectional random-access read =*p =*p =*p = *p access > > > >, [] write *p= *p= *p= *p= iterate ++ ++ ++ ++, ++,, +,, +=, -= compare ==,!= ==,!= ==,!= ==,!=, <, >, <=, >= Associative 3.24

(5): and Generic are a generalization of pointers, abstracting from their requirements in a way that allows a C++ program to work with different data structures in a uniform manner. act as intermediaries between containers and generic algorithms. Instead of operating on specific data types, algorithms are defined to operate on a range specified by a type of iterator. Any data structure that satisfies the requirements of the iterator may then be operated on by the algorithm. There are many examples of generic algorithms using iterators. Here are some examples sort sort a range into ascending order find find a value in a given range for_each apply a function to a range of elements set_union computes the union of two sets copy copy some range of elements to a new location remove remove elements equal to certain value Associative (6): Invalidation of STL are not secure in the sense that they can be or become invalid. There are several categories of invalid iterators. singular iterators past-the-end iterators out-of-range iterators dangling iterators inconsistent iterators We will formulate some rules for working with iterators Associative 3.25 3.26 (7): Invalidation of STL (8): Invalidation of STL : Singular Quote from the standard Rule 1 Never use invalid iterators. result of using invalid iterators is undefined expressions such as *iter, ++iter, etc. exhibit undefined behavior which can be anything from returning a valid and useful result to a program crash or reformatting of your hard-disk Associative can have singular values that are not associated with any container. Results of most expressions are undefined for singular values the only exception is an assignment of a non-singular value to an iterator that holds a singular value. In this case the singular value is overwritten the same way as any other value. s: Singular uninitialized pointers int* ptr default-constructed container iterators list<int>::iterator iter; default-constructed iterator adapters reverse_iterator<int*> riter dereferenceable and past-the-end values are non-singular Associative 3.27 3.28

(9): Invalidation of STL : Singular (10): Invalidation of STL : Singular singular iterators can be created singular iterators can be used inadvertently as input or output iterators int array[100]; int* begin, end; list<int> lst; list<int>::iterator out; copy(begin, end, out); //singular iterators Associative singular iterators are not associated with any container only assignment is defined results of most expressions are undefined for singular iterators only assignment of a non-singular iterator to a singular iterator is valid Rule 2 Never perform any operation on a singular iterator except assignment of a non-singular iterator Associative 3.29 3.30 (11): Invalidation of STL : Past-the-End (11): Invalidation of STL : Past-the-End s: non-dereferenceable past-the-end iterators Quote from the standard Just as a regular pointer to an array guarantees that there is a pointer value pointing past the last element of the array, so for any iterator type there is an iterator value that points past the last element of a corresponding container. These values are called past-the-end values. Values of an iterator i for which the expression *i is defined are called dereferenceable. The library never assumes that past-the-end values are dereferenceable. additional requirement in the standard: that can be incremented must be dereferenceable. Associative non-dereferenceable past-the-end iterators end-of-container iterator container.end() end-of-array iterator array+size end-of-input-stream iterator istream_iterator<t>() reverse past-the-end iterator container.rend() reverse end-of-array iterator reverse_iterator<elemt*>(array) : dereferenceable past-the-end iterator int arr[500];... int* where = find(arr,arr+100,5); //where++ is dereferenceable Associative 3.31 3.32

(12): Invalidation of STL : Past-the-End past-the-end iterators can be created past-the-end iterators can be used inadvertently as input or output iterators int array[100]; list<int> lst; copy(array,array+100,lst.begin()); //past-the-end iterator (13): Invalidation of STL : Out-of-Range Out-of-range iterators are iterators that have been advanced beyond the range of valid elements contained in a sequence. beyond the past-the-end iterator of the sequence via incrementing or pointer arithmetics beyond the beginning of the sequence via decrementing or pointer arithmetics The result of any operation on an out-of-range iterators is undefined. out-of-range iterators can inadvertently be created often implicitly inside an algorithm list is empty = begin iterator equals end iterator Rule 3 Never dereference or increment the past-the-end iterator of an iterator range. Associative 3.33 istream_iterator<string> in(cin),eof; vector<string> vec; vec.reserve(100); copy(in,eof,vec.begin()); //might be advanced beyond capacity algorithm might advance iterator beyond capacity unpredictable result: memory corruption without program crash Associative 3.34 (14): Invalidation of STL : Out-of-Range (15): Invalidation of STL : Out-of-Range out-of-range iterators can be created inadvertently whenever size of sequence is determined by information other than the sequence itself all algorithms that take output iterator size of output sequence determined by size of input sequence copy(), remove_copy_if(), transform(), merge(),... algorithms with more than one input sequence size of 2nd input sequence determined by size of 1st input sequence equal(), transform() Associative avoid problem: use inserters as output destination insert iterators have no valid range can be incremented infinitely often Rule 4 istream_iterator<string> in(cin),eof; vector<string> vec; back_insert_iterator<std::vector<string> > vecit(vec); copy(in, eof, vecit); //cannot be advanced beyond capacity Associative Prefer inserters as output destinations over regular iterators. 3.35 3.36

(15): Invalidation of STL : Dangling (16): Invalidation of STL : Dangling lifetime dependencies are frequently overlooked invalidation through operations is even less obvious A dangling iterator points to a sequence element : stream iterators depend on the stream that does not exists or was moved to a different memory location or is otherwise not accessible All operations on dangling iterators exhibit undefined behavior Dangling iterators can inadvertently be created due to lifetime dependencies due to operations that invalidate iterators Associative istream_iterator<string> in(ifstream( in.txt")), eof; ostream_iterator<string>(cout, \n ) out; copy(in, eof, out); //"in" is dangling iterator problem: lifetime of temporary stream object ceases at end of statement file closed dangling iterator possible results: program crash Associative Rule 5 Never use temporary stream objects in conjunction with stream iterators. 3.37 3.38 (17): Invalidation of STL : Dangling (18): Invalidation of STL : Dangling reallocation of a vector s internal array invalidates all iterators pointing to the vector reallocation can be triggered by iterators are pointer-like objects introduce the same lifetime dependencies as pointers sequence must live longer than iterator all operations on dangling iterators are illegal usually (but not always) lead to a program crash insert(), push_back() resize(), reserve() vector<int> v(10); Rule 6 are pointers. Keep an eye on lifetime dependencies between iterator and container. Associative p = v.begin(); for (int i = 0; i < 100; i++) { v.push_back(i); // p is dangling here Associative Rule 7 Don t re-use iterators pointing to elements in a vector after any calls to insert(), push_back(), resize() or reserve() 3.39 3.40

(19): Invalidation of STL : Inconsistent Inconsistent iterators are iterators that return unexpected values when they are dereferenced. can happen as a side-effect of erase() and insert() on vector or deque can be the result of a modifying algorithm Dereferencing an inconsistent iterator is invalid in the sense that it yields unexpected results. : Inconsistent iterator after modifying algorithm string arr[500];... fill with elements... string* where = find(arr,arr+500, Tom ); sort(arr,arr+500); cout << *where << endl; //need not print: Tom : Inconsistent iterator after erase() Associative (20): Invalidation of STL : Inconsistent Inconsistent iterators happen as side effect of container operations insert() and erase() on vector and deque modifying algorithms Rule 8 inplace algorithms (modify input sequence) remove(), sort(), partition(), replace(),... copy algorithms (modify output sequence) remove_copy(), transform(), merge(),... Don t re-use iterators pointing to elements in a container after any calls to insert(), erase() or to modifying algorithms. Associative vector<string> vec(arr,arr+500); vector<string>::iterator where = find(vec.begin(),vec.end(), Tom ); vec.erase(vec.begin(),where); cout << *where << endl; //need not print: Tom 3.41 3.42 1 2 STL provides a rich collection of generic algorithms 3 Applicable on containers and other sequences 4 5 Associative Three major categories exist: non-modifiying sequence operations mutating sequence operations sorting algorithms Associative 6 7 Associative 3.43 3.44

(2): Non-modifying sequence operations (3): Non-modifying sequence operations of the find() algorithm Non-modifying sequence operations do not modify the sequence on which they operate They provide: search for elements check for equality / unequality /... counting of elements... Associative It searches for an element in a given sequence Returns an iterator to the found element Returns iterator to one-past last element, like end(), if element couldn t be found Takes three arguments Iterator pointing to the beginning of the sequence Iterator pointing to the end of the sequence (one past last element!) The value to be matched Associative 3.45 3.46 (4): Non-modifying sequence operations (5): Mutating Sequence Operations Find in a List or an Array #include <algorithm> // definition of find() #include <list> #include <iostream> using namespace std; int main() { char lc1[] = { A, T, L ; // Initialize a list with the same elements list<char> lc(lc1, lc1+3); // find A in the list list<char>::iterator p = find( lc.begin(), lc.end(), A ); // find A in the array char* p1 = find(lc1, lc1+3, A ); // was A found? if(p!= lc.end()) *p = S ; // then replace it with S if(p1!= lc1 + 3) *p1 = S ; // then replace it with S Associative Mutating sequence operations modify the sequence on which they operate We have for example: copy fill replace transform... Associative while(p!= lc.end()) cout << *p++; cout << endl; while( p1!= lc1+3 ) cout << *p1++; cout << endl; // display the modified list // Output: STL // display the modified array // Output: STL 3.47 3.48

(6): Mutating Sequence Operations (7): Mutating Sequence Operations of the copy() algorithm It provides a generic copy function Copies a sequence of objects to a specific target Returns an iterator pointing to the one-past the last element copied Takes three arguments Iterator pointing to the beginning of the sequence to be copied Iterator pointing to the end of the sequence (one past last element!) Output iterator pointing to the first element of the destination range The destination range must have enough space to get the copy If possible use an insert iterator Associative 3.49 copy with normal iterator #include <algorithm> #include <list> #include <vector> using namespace std; int main(){ list<int> li; vector <int> vi; for (int i = 1; i <= 10; i++) li.push_back(i); // must make room for copied elements in advance vi.resize( li.size() ); // copy list elements into vector, starting at vector s beginning copy(li.begin(), li.end(), vi.begin()); copy with insert iterator int main(){ list<int> li; vector <int> vi; for (int i = 1; i <= 10; i++) li.push_back(i); copy(li.begin(), li.end(), back_insert_iterator<vector<int> >(vi)); Associative 3.50 (8): Sorting algorithms (9): Sorting algorithms of the sort() algorithm This category contains algorithms for sorting and merging sequences We have for example: sort partial_sort binary_search lower_bound... Associative Provides a generic sorting algorithm Sorts the elements in a given range (default is ascending order) No return Takes two arguments, optionally three Iterator pointing to the beginning of the sequence to be sorted Iterator pointing to the end of the sequence (one past last element!) to be sorted Optional predicate argument that is a pointer to a binary-returning predicate function (less-than) Associative Descending order sorting can be done by using the reverse iterators 3.51 3.52

(10): Sorting algorithms (11): Sorting algorithms example: sorting a sequence #include <iostream> #include <algorithm> //definition of sort() #include <vector> #include <cstdlib> using namespace std; int main() { vector <int> vi; for(int i = 0; i < 40; i++) vi.push_back(rand()%200); // sort vi; default is ascending order sort(vi.begin(), vi.end()); for(int i = 0; i < 40; i++) cout << vi[i] << ", "; cout << endl; Associative The sorting algorithm has some requirements to the container elements: The relational operators == and < must exist User-defined types without these operators can use containers, but cannot use the sort algorithm. In this case the user can supply a less_than function. example: sort algorithm with user defined order // Compare Function to sort int s in descending order bool less_than(int a, int b) { return b<a; int main() { vector <int> vi; for(int i = 0; i < 40; i++) vi.push_back(rand()%200); Associative // Now sort in descending order sort(vi.rbegin(), vi.rend()); for(int i = 0; i < 40; i++) cout << vi[i] << ", "; cout << endl; // sort vi; in descending order sort(vi.begin(), vi.end(), less_than); for(int i = 0; i < 40; i++) cout << vi[i] << ", "; cout << endl; 3.53 3.54 (12): How to Create a Generic Algorithm The creation of a generic algorithm can be done through different steps As an example, we want to evolve a generic binary search algorithm out of a conventional one. The starting point is a C++ binary search algorithm for integer Arrays. (13): How to Create a Generic Algorithm Assumptions binary_search makes about its environment: The elements of the array must be integers. To make it work with arrays of arbitrary types we transform binary_search in a template function. Also in case of an unsuccessful search we return the pointer array + n (a past-the-end pointer!) instead of null. const int* binary_search( const int* array, int n, int x ) { const int* lo = array, *hi = array + n, *mid; while( lo!= hi ) { mid = lo + (hi - lo) / 2; if( x == *mid ) return mid; if( x < *mid ) hi = mid; else lo = mid + 1; return 0; Associative template<class T> const T* binary_search(const T* array, int n, const T& x ) { const T* lo = array, *hi = array + n, *mid; while( lo!= hi ) { mid = lo + (hi - lo) / 2; if( x == *mid ) return mid; if( x < *mid ) hi = mid; else lo = mid + 1; return array + n; Associative 3.55 3.56

(14): How to Create a Generic Algorithm (15): How to Create a Generic Algorithm Instead of handing over array as pointer to the first element and a size, we could also specify a pointer to the first and past the last element to approach STL s iterator concept. The last step is to change from pointers to iterators Since binary_search needs a random-access iterator we will name the type of first and last RandomAccessIterator. template<class T> const T* binary_search(t* first, T* last, const T& x ) { T* not_found = last, *mid; while(first!= last) { mid = first + (last - first) / 2; if( x == *mid ) return mid; if( x < *mid ) last = mid; else first = mid + 1; return not_found; Associative template<class RandomAccessIterator, class T> const RandomAccessIterator binary_search(randomaccessiterator first, RandomAccessIterator last, const T& x ) { RandomAccessIterator not_found = last, mid; while(first!= last) { mid = first + (last - first) / 2; if( x == *mid ) return mid; if( x < *mid ) last = mid; else first = mid + 1; return not_found; Associative 3.57 3.58 (16): How to Create a Generic Algorithm The only assumptions the algorithm makes are: the random access to elements of type T between the two iterators and that operator== and operator< are defined for type T and the value type of the iterator. The algorithm hasn t lost anything of its functionality, especially not when dealing with built in types. 1 2 3 int main() { int array[high]; int search;... Fill the array... Associative 4 5 Associative vector<int> vec(array, array + HIGH); // Search in array const int* p = binary_search(ar, ar + HIGH, search); // Search in vector vector<int>::iterator it; it = binary_search(v.begin(), v.end(), search); 6 7 Associative 3.59 3.60

(2) The next examples shows how Functors may be used : Generic binary search Callback functions can be invoked by using function pointers (old style, C) OO environments accept functions encapsulated in a function object (also called Functor) Functors are more resilient, the object can be modified without affecting its users Compilers can inline functors (nearly impossible with function pointers) Functors can be generic, they can embody generic algorithms by means of member templates Function objects are discussed in more details in a separate chapter (usage also outside of STL) Associative template<class RandomAccessIterator, class T, class F> const RandomAccessIterator binary_search(randomaccessiterator first, RandomAccessIterator last, const T& x, F less) { RandomAccessIterator not_found = last, mid; while(first!= last) { mid = first + (last - first) / 2; if(less(x, *mid)) last = mid; else if (less(*mid, x)) first = mid + 1; else return mid; return not_found; class Less { public: bool operator()(int a, int b) { return a < b; ; Associative it = binary_search(v.begin(), v.end(), search, Less()); 3.61 3.62 Associative 1 2 Associative containers are also called Associative arrays 3 They can use index, which need not to be an integer An associative array is also called map or dictionary 4 C++ STL defines several associative arrays: 5 6 Associative map multimap set multiset Associative 7 Associative 3.63 3.64

Associative (2): Map The map can be seen as a sort of vector or deque Two main differences exist: The index values (also called key values) needn t to be integers, but can be any ordered data type The map can be indexed by real numbers for example The key value must be a data type that has a comparison operator Elements can be accessed through the subscript operator or through any other known accessing technique The map is an ordered structure Elements are kept in a sequence, the ordering is determined by the key value Retrieves rapidly the elements (logarithmic time, ordered structure) No limit in size (varies like lists) Map is a set that maintains a collection of pairs The map data structure demands unique key values One-to-one association between key element and corresponding value Adding a new element with an existing key is ignored! Associative Associative (3): Map The map is a template data structure that is specialized by Type of the key elements Type of the associated elements Operator used in comparing key (optional) /* * map indexed by doubles containing strings */ map<double, string, less<double> > map_one; /* * map indexed by integers, containing integers Associative * map is initialized by elements form "acontainer"\usepackage{pgfpages \pgfpagesuselayout{4 on 1[a4paper,landscape,border shrink=5mm] */ map<int, int> map_two(acontainer.begin(), acontainer.end()); /* * create a new map, initializing it from map two */ map<int, int> map_three(map_two); 3.65 3.66 Associative (4): Map Type Definitions Associative (5): Map Type Definitions Map and multimap include a number of type definitions Type key_type value_type mapped_type iterator const_iterator reverse_iterator const_reverse_iterator reference const_reference size_type key_compare value_compare difference_type allocator_type Definition The type associated with the keys used to index the map. The type held by the container, a key/value pair. The type associated with values. A Bidirectional iterator An iterator that does not allow modification of the underlying sequence. An iterator that moves in a backward direction. A combination constant and reverse iterator. A reference to an underlying value. A reference to an underlying value that will not permit the element to be modified. An unsigned integer type, used to refer to the size of containers. A function object that can be used to compare two keys. A function object that can be used to compare two elements. A signed integer type, used to describe the distances between iterators. An allocator used by the container for all storage management. Associative : Usage of map types // Defining a map indexed by ints containing strings map<int, string> mymap; // Defining an iterator for a map indexed by ints containing strings map<int, string>::iterator it; // Define an Element of the map. This is a pair map<int, string>::value_type element(2, "Hello world"); mymap.insert(element); cout << element.first << ", " << element.second << endl; // Define the compare operator for the map map<int, string>::key_compare comp; if(comp(i, j)) cout << "element i is less than j" << endl; Associative 3.67 3.68

Associative (6): Insert and Access Elements in a Map Values can be inserted into a map by using the insert() operation The subscript operator can also be used for insertion of new elements The subscript operator can also be used to access the elements Warning: Accessing a nonexistent element will create this element. int main() { map<string, string> amap; pair<map<string, string>::iterator, bool> ret; /* * Insert elements with "insert()" */ ret = amap.insert( map<string, string>::value_type("pierre", "Fierz")); ret = amap.insert( map<string, string>::value_type("pierre", "Müller")); if (!ret.second) { cout << "Element: " << ret.first->first << " already in map with value: " << ret.first->second << endl; Associative 3.69 Associative (7): Insert and Access Elements in a Map : continue /* * Insert element with subscript operator [] */ amap["jacques"] = "Boillat"; /* * Access element with [] */ cout << amap["jacques"] << endl; string s = amap["hans"]; // creates a new element with value "" map<string, string>::iterator it = amap.begin(); while (it!= amap.end()) cout << (it++)->first << ", "; // output: Hans, Jacques, Pierre, cout << endl; /* * Remove "Hans from the map */ amap.erase("hans"); it = amap.begin(); while (it!= amap.end()) cout << (it++)->first << ", "; // output: Jacques, Pierre, cout << endl; Associative 3.70 Associative (8): Multimap Associative (9): Set In a multimap a key can occur more than once. The subscript operator [] is not defined for multimaps. The erase(k) function deletes all elements with the given Key k. The function count(k) returns the number of elements with key k in the map. Insert is always successfull. Valid for set and multiset Insertion or removal does not invalidate iterators The key of an element is constant and can t be modified. The value of an element can be modified. Multiple operations using (multi)maps are provided by the STL Searching Counting Element comparison for_each(), adjacent_find(), accumulate(),... Associative A set is a collection of value The set is an ordered container Comparable with a list, except the ordering Comparable with a map, but the element is also the key Optimized for insertion and removal of elements (logarithmic number of steps) Also optimized for set operations (O(n log(n))) Not size limited, expands and shrinks dynamically In the set The element is the key The element is unique In the set, the insertion of an existing element is ignored! Associative 3.71 3.72

Associative (10): Set constructor Associative (11): Insert and Erase in Sets The set is a template data structure that is specialized by Type of the elements (which are also the key) Operator used to compare keys (optional). If not provided, the element type s less-than operator is used The element type must recognize both Equality testing operator == Less-than comparison operator < A set can be declared with no initial elements (empty) initialized from another container providing a pair of iterators //An empty set containing strings set<string, less<string> > set_one; Associative Values can be inserted into sets uniquely by using the insert() operation The method returns a pair of values An iterator pointing to the element Boolean, true if the element was inserted, else false Already existing elements won t be inserted in sets Subscript operator does not exist for sets; The erase() operation removes the elements from the set Underlying objects are cleanly destroyed with its class destroyer method Associative // A set containing int, initialized with a range of another set set<int> set_two(acontainer.begin(), acontainer.end()); //create a new set, initializing it from set two set<int> set_three(set_two); Existing elements can not be modified directly Would need a resorting of the set If an existing element must be modified, then remove the old element and add the new element 3.73 3.74 Associative (12): Insert and Erase in Sets Associative (13): Set operations int main() { set<int> s1; pair<set<int>::iterator, bool> p; int aset[] = {7, 5, 3, 11, 17, 19, 13, 2, 4, 6; int *it = aset; /* * Insert some elements in the set */ p = s1.insert(1); p = s1.insert(2); p = s1.insert(1); if (!p.second) { cout << "Element: " << *(p.first) << " already exists" << endl; s1.insert(it, it + 10); set<int>::iterator it1 = s1.begin(); while (it1!= s1.end()) { cout << *it1 << ", "; ++it1; cout << endl; // output: 1, 2, 3, 4, 5, 6, 7, 11, 13, 17, 19, /* * Erase some elements */ s1.erase(39); // element doesn t exist => No effect s1.erase(17); // element 17 erased Associative 3.75 find() and count() are member functions and can be used to test if an element is in a set. empty() is a member function wich tests if the set is empty. int main() { int aset[] = {7, 5, 3, 11, 17, 19, 13, 2, 4, 6; set<int> s1(aset, aset + 10); set<int> s2; set<int>::iterator it = s1.find(19); if (it!= s1.end()) cout << *it << endl; //output: 19 if (s1.count(5) == 1) cout << "Element 5 is in set" << endl; if (s2.empty()) cout << "s2 is the empty set" << endl; Associative 3.76

Associative (14): Set operations Associative (15): Set operations Most set operations are implemented as algorithms. includes() can be used to test if a set is a subset of another set All set construction operators are provided. set_union() set_intersection() set_difference() set_symmetric_difference() The set construction functions take all the same kind of arguments The first two argument delimit the first set The third and fourth argument delimit the second set The fifth element is an insert iterator, were the result will be put Associative int main() { int aset1[] = {2, 3, 4, 5, 6, 7, 11, 13, 17, 19; set<int> s1(aset1, aset1 + 10); int aset2[] = {1, 2, 11, 19, 23, 27, 33; set<int> s2(aset2, aset2 + 7); set<int> s3; set_union(s1.begin(), s1.end(), s2.begin(), s2.end(), insert_iterator<set<int> >(s3, s3.begin())); for (set<int>::iterator p = s3.begin(); p!= s3.end(); ++p) cout << *p << ", "; cout << endl; //output: 1, 2, 3, 4, 5, 6, 7, 11, 13, 17, 19, 23, 27, 33, s3.clear(); set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(), insert_iterator<set<int> >(s3, s3.begin())); for (set<int>::iterator p = s3.begin(); p!= s3.end(); ++p) cout << *p << ", "; cout << endl; //output: 2, 11, 19, s3.clear(); set_difference(s1.begin(), s1.end(), s2.begin(), s2.end(), insert_iterator<set<int> >(s3, s3.begin())); for (set<int>::iterator p = s3.begin(); p!= s3.end(); ++p) cout << *p << ", "; cout << endl; //output: 3, 4, 5, 6, 7, 13, 17, s3.clear(); set_symmetric_difference(s1.begin(), s1.end(), s2.begin(), s2.end(), insert_iterator<set<int> >(s3, s3.begin())); for (set<int>::iterator p = s3.begin(); p!= s3.end(); ++p) cout << *p << ", "; cout << endl; //output: 1, 3, 4, 5, 6, 7, 13, 17, 23, 27, 33, Associative 3.77 3.78 Associative (16): Multiset Multisets are associative containers with the same properties as set containers, but allowing for multiple keys with equal values. Differences in operations between sets and multisets : count() returns the number of times the element appears in the container. erase() removes all elements with the given key. set_union() of two multisets. s 1 s 2 = {x (x s 1 x s 2 ) count(s 1 s 2, x) = max(count(s 1, x), count(s 2, x)) set_intersection() of two multisets Associative s 1 s 2 = {x x s 1 x s 2 count(s 1 s 2, x) = min(count(s 1, x), count(s 2, x)) set_difference() of two multisets s 1 \ s 2 = {x x s 1 count(s 1, x) > count(s 2, x) count(s 1 \ s 2, x) = count(s 1, x) count(s 2, x) 3.79