Chapter 20 - Chapter 20 The STL The (containers, iterators,...

Info iconThis preview shows page 1. Sign up to view the full content.

View Full Document Right Arrow Icon
This is the end of the preview. Sign up to access the rest of the document.

Unformatted text preview: Chapter 20 The STL The (containers, iterators, and algorithms) Bjarne Stroustrup www.stroustrup.com/Programming Abstract Abstract This lecture and the next present the STL – the This containers and algorithms part of the C++ standard library library The STL is an extensible framework dealing with The data in a C++ program. First, I will present the general ideal, then the First, fundamental concepts, and finally examples of containers and algorithms. The key notions of sequence and iterator used to tie The sequence iterator data together with algorithms (for general processing) are also presented. Stroustrup/Programming 2 Overview Overview Common tasks and ideals Generic programming Containers, algorithms, and iterators The simplest algorithm: find() Parameterization of algorithms Sequence containers map, set Standard algorithms vector and list Associative containers find_if() and function objects copy, sort, … Input iterators and output iterators List of useful facilities Headers, algorithms, containers, function objects Stroustrup/Programming 3 Common tasks Common Collect data into containers Organize data Retrieve data items For printing For fast access By index (e.g., get the Nth element) By By value (e.g., get the first element with the value "Chocolate") "Chocolate" By By properties (e.g., get the first elements where “age<64”) (e.g., By Add data Remove data Sorting and searching Simple numeric operations Stroustrup/Programming 4 Observation Observation We can (already) write programs that are very similar We independent of the data type used independent Using an int isn’t that different from using a double Using int double Using a vector<int> isn’t that different from using a Using vector<int> vector<string> vector<string> Stroustrup/Programming 5 Ideals Ideals We’d like to write common programming tasks so that we We’d don’t have to re-do the work each time we find a new way of storing the data or a slightly different way of interpreting the data interpreting Finding a value in a vector isn’t all that different from Finding vector finding a value in a list or an array list Looking for a string ignoring case isn’t all that different Looking string from looking at a string not ignoring case string Graphing experimental data with exact values isn’t all that Graphing different from graphing data with rounded values different Copying a file isn’t all that different from copying a vector Stroustrup/Programming 6 Ideals (continued) (continued) Code that’s Uniform access to data Easy to read Easy to modify Regular Short Short Fast Fast Independently of how it is stored Independently of its type … Stroustrup/Programming 7 Ideals (continued) (continued) … Type-safe access to data Easy traversal of data Compact storage of data Fast Retrieval of data Addition of data Deletion of data Standard versions of the most common algorithms Copy, find, search, sort, sum, … Stroustrup/Programming 8 Examples Sort a vector of strings Find an number in a phone book, given a name Find the highest temperature Find all values larger than 800 Find the first occurrence of the value 17 Sort the telemetry records by unit number Sort the telemetry records by time stamp Find the first value larger than “Petersen”? What is the largest amount seen? Find the first difference between two sequences Compute the pair wise product of the elements of two sequences What’s the highest temperatures for each day in a month? What’s the top 10 best-sellers? What’s the entry for “C++” (say, in Google)? What’s the sum of the elements? Stroustrup/Programming 9 Generic programming Generalize algorithms Sometimes called “lifting an algorithm” The aim (for the end user) is Increased correctness Greater range of uses Possibilities for re-use Better performance Through better specification Through wider use of tuned libraries Unnecessarily slow code will eventually be thrown away Go from the concrete to the more abstract The other way most often leads to bloat 10 10 Lifting example (concerte algorithms) (concerte Lifting double sum(double array, int n) // one concrete algorithm (doubles in array) // one { double s = 0; for (int i = 0; i < n; ++i ) s = s + array[i]; return s; } struct Node { Node* next; int data; }; int sum(Node* first) { int s = 0; while (first) { s += first->data; first = first->next; } return s; } // another concrete algorithm (ints in list) // another 11 11 Lifting example (abstract the data structure) (abstract Lifting // pseudo-code for a more general version of both algorithms // pseudo-code int sum(data) // somehow parameterize with the data structure // somehow { int s = 0; // initialize // initialize while (not at end) { // loop through all elements // loop s = s + get value; // compute sum get // compute get next data element; get } return s; // return result // return } We need three operations (on the data structure): not at end get value get next data element 12 12 Lifting example (STL version) (STL Lifting // Concrete STL-style code for a more general version of both algorithms // Concrete template<class Iter, class T> template<class T sum(Iter first, Iter last, T s) { while (first!=last) { while s = s + *first; ++first; } return s; } // Iter should be an Input_iterator Iter // T should be something we can + and = // should // T is the “accumulator type” // is Let the user initialize the accumulator float a = { 1,2,3,4,5,6,7,8 }; float double d = 0; double d = sum(a,a+sizeof(a)/sizeof(*a),d); 13 13 Lifting example Almost the standard library accumulate I simplified a bit for terseness simplified (see 21.5 for more generality and more details) Works for Runs as fast as “hand-crafted” code arrays vectors lists istreams … Given decent inlining The code’s requirements on its data has become explicit We understand the code better 14 14 The STL The Part of the ISO C++ Standard Library Mostly non-numerical Only 4 standard algorithms specifically do computation Handles textual data as well as numeric data E.g. string Deals with organization of code and data Accumulate, inner_product, partial_sum, adjacent_difference Built-in types, user-defined types, and data structures Optimizing disk access was among its original uses Performance was always a key concern Stroustrup/Programming 15 The STL The Designed by Alex Stepanov General aim: The most general, most efficient, most flexible representation of concepts (ideas, algorithms) Represent separate concepts separately in code Combine concepts freely wherever meaningful General aim to make programming “like math” or even “Good programming is math” or is works for integers, for floating-point numbers, for works polynomials, for … polynomials, Stroustrup/Programming 16 Basic model Basic Algorithms sort, find, search, copy, … • Separation of concerns – Algorithms manipulate Algorithms data, but don’t know about containers about – Containers store data, but Containers iterators don’t know about algorithms algorithms – Algorithms and Algorithms containers interact through iterators through Containers • Each container has its Each own iterator types own vector, list, map, hash_map, … vector, Stroustrup/Programming 17 The STL The An ISO C++ standard framework of about 10 An containers and about 60 algorithms connected by iterators iterators Other organizations provide more containers and Other algorithms in the style of the STL algorithms Boost.org, Microsoft, SGI, … Probably the currently best known and most widely Probably used example of generic programming used Stroustrup/Programming 18 The STL The If you know the basic concepts and a few examples you If can use the rest can Documentation SGI Dinkumware http://www.dinkumware.com/refxcpp.html (beware of several library http://www.dinkumware.com/refxcpp.html versions) versions) Rogue Wave http://www.sgi.com/tech/stl/ (recommended because of clarity) http://www.roguewave.com/support/docs/sourcepro/stdlibug/index.html More accessible and less complete documentation Appendix B Stroustrup/Programming 19 Basic model Basic A pair of iterators define a sequence The beginning (points to the first element – if any) The end (points to the one-beyond-the-last element) begin: end: … • An iterator is a type that supports the “iterator operations” • • • ++ Go to next element * Get value == Does this iterator point to the same element as that iterator? • Some iterators support more operations (e.g. --, +, and [ ]) Stroustrup/Programming 20 Containers Containers (hold sequences in difference ways) vector 0 2 3 list (doubly linked) 1 0 2 1 6 set (a kind of tree) 2 0 7 1 5 3 Stroustrup/Programming 4 21 The simplest algorithm: find() find() … begin: // Find the first element that equals a value // Find template<class In, class T> In find(In first, In last, const T& val) { while (first!=last && *first != val) ++first; return first; } end: void f(vector<int>& v, int x) // find an int in a vector // find { vector<int>::iterator p = find(v.begin(),v.end(),x); if (p!=v.end()) { /* we found x */ } if */ // … // } We can ignore (“abstract away”) the differences between containers Stroustrup/Programming 22 find() find() generic for both element type and container type void f(vector<int>& v, int x) // works for vector of ints // vector int { vector<int>::iterator p = find(v.begin(),v.end(),x); if (p!=v.end()) { /* we found x */ } if we */ // … // } void f(list<string>& v, string x) // works for list of strings // list string { list<string>::iterator p = find(v.begin(),v.end(),x); if (p!=v.end()) { /* we found x */ } if we */ // … // } void f(set<double>& v, double x) // works of set of doubles // set double { set<double>::iterator p = find(v.begin(),v.end(),x); if (p!=v.end()) { /* we found x */ } if */ // … // } Stroustrup/Programming 23 Algorithms and iterators Algorithms An iterator points to (refers to, denotes) an element of a sequence The end of the sequence is “one past the last element” not “the last element” not That’s necessary to elegantly represent an empty sequence One-past-the-last-element isn’t an element You can compare an iterator pointing to it You can’t dereference it (read its value) Returning the end of the sequence is the standard idiom for “not Returning found” or “unsuccessful” found” some iterator: An empty sequence: the end: 0 1 2 3 Stroustrup/Programming 24 Simple algorithm: find_if() find_if() Find the first element that match a criterion (predicate) Here, a predicate takes one argument and returns a bool Here, bool template<class In, class Pred> In find_if(In first, In last, Pred pred) { while (first!=last && !pred(*first)) ++first; return first; } A predicate void f(vector<int>& v) { vector<int>::iterator p = find_if(v.begin(),v.end,Odd()); if (p!=v.end()) { /* we found an odd number */ } if */ // … // } Stroustrup/Programming 25 Predicates Predicates A predicate (of one argument) is a function or a function object predicate that takes an argument and returns a bool bool For example A function bool odd(int i) { return i%2; } // % is the remainder (modulo) operator bool is odd(7); // call odd: is 7 odd? call A function object struct Odd { bool operator()(int i) const { return i%2; } }; Odd odd; // make an object odd of type Odd // make of odd(7); // call odd: is 7 odd? // odd Stroustrup/Programming 26 Function objects Function A concrete example using state template<class T> struct Less_than { T val; // value to compare with // value Less_than(int x) :val(x) { } bool operator()(const T& x) const { return x < val; } }; // find x<43 in vector<int> : // find p=find_if(v.begin(), v.end(), Less_than(43)); p=find_if(v.begin(), // find x<“perfection” in list<string>: find “perfection” in q=find_if(ls.begin(), ls.end(), Less_than("perfection")); q=find_if(ls.begin(), Stroustrup/Programming 27 27 Function objects Function A very efficient technique inlining very easy Faster than equivalent function and effective with current compilers And sometimes you can’t write an equivalent function The main method of policy parameterization in the STL Key to emulating functional programming techniques in C++ Stroustrup/Programming 28 Policy parameterization Policy Whenever you have a useful algorithm, you eventually want to Whenever parameterize it by a “policy”. parameterize For example, we need to parameterize sort by the comparison criteria struct Record { string name; char addr[24]; // … // }; // standard string for ease of use // standard // old C-style string to match database layout // old vector<Record> vr; // … // sort(vr.begin(), vr.end(), Cmp_by_name()); sort(vr.begin(), vr.end(), Cmp_by_addr()); Stroustrup/Programming // sort by name // sort // sort by addr // sort 29 Comparisons Comparisons // Different comparisons for Rec objects: // Different objects struct Cmp_by_name { bool operator()(const Rec& a, const Rec& b) const { return a.name < b.name; } // look at the name field of Rec return look }; struct Cmp_by_addr { bool operator()(const Rec& a, const Rec& b) const { return 0 < strncmp(a.addr, b.addr, 24); } }; // correct? // correct? // note how the comparison function objects are used to hide ugly // note // and error-prone code // and Stroustrup/Programming 30 30 vector vector template<class T> class vector { T* elements; // … // typedef ??? iterator; // the type of an iterator is implementation defined // the // and it (usefully) varies (e.g. range checked iterators) // and // a vector iterator could be a pointer to an element // vector typedef ??? const_iterator; iterator begin(); // points to first element // points const_iterator begin() const; const_iterator iterator end(); // points one beyond the last element iterator // points const_iterator end() const; iterator erase(iterator p); iterator insert(iterator p, const T& v); // remove element pointed to by p // remove // insert a new element v before p // }; Stroustrup/Programming 31 insert() into vector insert() vector<int>::iterator p = v.begin(); ++p; ++p; ++p; vector<int>::iterator q = p; ++q; v: q: 6 p: 0 1 2 3 4 5 p=v.insert(p,99); // leaves p pointing at the inserted element leaves pointing v: q: p: 7 0 1 2 99 3 4 5 Note: q is invalid after the insert() Note: Some elements moved; all elements could have moved Note: Stroustrup/Programming Stroustrup/Programming 32 erase() from vector erase() v: 7 0 p = v.erase(p); v: q: p: 1 2 99 3 4 5 // leaves p pointing at the element after the erased one // leaves pointing q: p: 6 0 1 2 3 4 5 vector elements move when you insert() or erase() Iterators into a vector are invalidated by insert() and erase() Stroustrup/Programming 33 list list Link: T value Link* pre Link* post template<class T> class list { Link* elements; // … // typedef ??? iterator; // the type of an iterator is implementation defined // the // and it (usefully) varies (e.g. range checked iterators) // and // a list iterator could be a pointer to a link node // list typedef ??? const_iterator; iterator begin(); // points to first element // points const_iterator begin() const; const_iterator iterator end(); // points one beyond the last element iterator // points const_iterator end() const; iterator erase(iterator p); iterator insert(iterator p, const T& v); // remove element pointed to by p // remove // insert a new element v before p // }; Stroustrup/Programming 34 insert() into list insert() list<int>::iterator p = v.begin(); ++p; ++p; ++p; list<int>::iterator q = p; ++q; v: 6 0 v = v.insert(p,99); v: q: p: 1 2 3 0 5 // leaves p pointing at the inserted element p: 7 4 1 q: 2 Note: q is unaffected Note: No elements moved around 3 4 5 99 Stroustrup/Programming 35 erase() from list erase() v: p: 7 0 q: 1 2 3 4 5 99 p = v.erase(p); v: // leaves p pointing at the element after the erased one q: p: 6 0 1 2 3 4 5 Note: list elements do not move when you insert() or erase() Stroustrup/Programming 36 Ways of traversing a vector Ways for(int i = 0; i<v.size(); ++i) … // do something with v[i] do // why int? // why for(vector<int>::size_type i = 0; i<v.size(); ++i) … // do something with v[i] do // longer but always correct // longer for(vector<int>::iterator p = v.begin(); p!=v.end(); ++p) … // do something with *p // do know both ways (iterator and subscript) The subscript style is used in essentially every language The iterator style is used in C (pointers only) and C++ The iterator style is used for standard library algorithms The subscript style doesn’t work for lists (in C++ and in most languages) use either way for vectors There are no fundamental advantage of one style over the other But the iterator style works for all sequences Prefer size_type over plain int Prefer size_type int pedantic, but quiets compiler and prevents rare errors Stroustrup/Programming 37 Some useful standard headers Some <iostream> <fstream> <algorithm> <numeric> <functional> <string> <vector> <map> <list> <set> I/O streams, cout, cin, … file streams sort, copy, … accumulate, inner_product, … function objects Stroustrup/Programming 38 Next lecture Next Map, set, and algorithms Stroustrup/Programming 39 ...
View Full Document

This note was uploaded on 02/18/2012 for the course CSCE 121 taught by Professor Walter daugherity during the Fall '09 term at Texas A&M.

Ask a homework question - tutors are online