105 - Texas A&M University

Download Report

Transcript 105 - Texas A&M University

CSCE 121:509-512
Introduction to Program Design and Concepts, Honors
J. Michael Moore
Spring 2015
Set 19: The STL: Containers and Iterators
1
The STL
• STL = Standard Template Library
• Part of the C++ standard library
• Extensible framework for dealing with data in
C++ programs
• Key notions of sequence and iterator tie
together data and algorithms
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
2
Common Programming Tasks
• Collect multiple data items into a container
• Organize the data according to some rule
• Retrieve data items
– by index: e.g., get the i-th item
– by value: e.g., get the first item with the value “Chocolate”
– by properties: e.g., get the first item with age < 64
•
•
•
•
Add new data items
Remove existing data items
Sorting and searching
Simple numeric operations (e.g., add them all up)
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
3
Key Observation
• Most of the work to do these programming
tasks is independent of the actual type of the
data types or even how the data is stored!
• E.g., for sorting, we just need a way to
compare the data items
– numeric types, use <
– strings, use lexicographic (alphabetical) order
• E.g., arrays and linked lists have a lot in
common
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
4
Ideal
• Write code for common programming tasks
that does not have to be rewritten every time
we come up with a different way to store the
data
• E.g., searching in a vector vs. an array vs. a
linked list is not all that different conceptually
• That is, we want uniform access to the data
– independent of how it is stored
– independent of its type
• And be easy to read, easy to modify, fast,…
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
5
Generic Programming
• Generalize algorithms
– in addition to generalizing data structures
• Advantages:
– increased correctness
– greater range of uses (and reuses)
– better performance (through tuned libraries)
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
6
Sum Function for Array
double sum(double array[], int n)
// assume array is of size n
{
double s = 0;
for (int i = 0; i < n; ++i)
s = s + array[i];
return s;
}
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
7
Sum Function for Linked List
struct Node {
Node* next;
int data;
};
int sum(Node* first) {
int s = 0;
while (first) {
s+= first->data;
first = first->next;
}
return s;
}
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
8
Pseudocode Version of Both
Functions
int sum(data) {
int s = 0;
while (not at end) {
// operation 1
s = s + get value;
// operation 2
get next data element; // operation 3
}
return s;
}
I.e., initialize sum to 0, loop through all the elements
adding them to the sum, and return the sum.
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
9
STL-Style Version of Generalized
Sum Function
// Iter must be an “Input_iterator”
// T must be a type that can be added and assigned
template<class Iter, class T>
// first and last refer to data elements;
// s accumulates the sum
T sum(Iter first, Iter last, T s) {
while (first != last) { // operation 1
s = s + *first;
// operation 2
++first;
// operation 3
}
return s;
}
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
10
Using STL-Style Sum Function
float a[] = {1,2,3,4,5,6,7,8};
double d = 0;
d = sum(a,a+sizeof(a)/sizeof(*a),d);
• First initialize the array a.
• Then initialize the accumulator d.
• Then call the templated function sum:
– Iter is replaced with double*
– T is replaced with double
• First argument is a pointer to the first element of a.
• Second argument is a pointer to just after the last element of a
(why?).
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
11
Instantiated Sum Function
double sum(double* first, double* last, double s) {
while (first != last) {
s = s + *first;
++first;
}
return s;
}
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
12
Sum Function Example
•
•
•
•
Almost the standard library accumulate()
Works for arrays, vectors, lists, istreams,…
Runs as fast as “hand-crafted” code
Code’s requirements on the data are made
explicit
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
13
Basic STL Model
• Algorithms
• Separation of concerns
sort, find, search, copy, …
iterators
• Containers
– Algorithms manipulate
data, but don’t know
about containers
– Containers store data,
but don’t know about
algorithms
– Algorithms and
containers interact
through iterators
• Each container has its
own iterator types
vector, list, map, unordered_map, …
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
14
Iterators
• A pair of iterators defines a sequence
– the beginning (points to first element, if any)
– the end (points to the one-beyond-the-last
element)
begin:
end:
…
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
15
Iterators
begin:
end:
…
• An iterator is a type that supports the “iterator
operations”:
– Go to next element: ++
– Get value: *
– Check if two iterators point to same element: ==
• Frequently a pointer type, but not necessarily
• Some iterators support more operations (--, +, [ ] )
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
16
One-Past-The-Last
• An iterator point to (refers to, denotes) an element of a
sequence
• The end of the sequence is “one past the last element”, not
the last element!
• Reason is to elegantly represent an empty sequence
• One-past-the last element is not an element
– you can compare an iterator pointing to it
– but you cannot dereference it (get its value)
An empty sequence:
some
iterator:
begin:
the end:
0
1
2
end:
3
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
17
Containers
Hold sequences in different ways
• vector
0
1
2
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
3
18
Containers
Hold sequences in different ways
• list (doubly-linked)
2
0
1
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
19
Containers
Hold sequences in different ways
• set (a kind of tree)
6
2
0
7
1
5
3
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
4
20
STL find() algorithm
// find first element that equals a value
template<class In, class T>
In find(In first, In last, const T& val) {
while (first != last && *first != val) ++first;
return first;
}
// sample use of find, for vector
void f(vector<int>& v, int x) {
vector<int>::iterator p = find(v.begin(),v.end(),x);
if (p != v.end()) { /* we found x */}
// ...
}
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
21
More About STL find() Function
• It is generic in two aspects
– element type (sequence of any kind of data)
– container type (is the sequence implemented with
an array, a vector, a linked list, …?)
• The next slide shows how similar the code is
between
– a vector of ints
– a list of strings
– a set of doubles
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
22
Comparing Different Uses of find()
void f(vector<int>& v, int x) {
vector<int>::iterator p = find(v.begin(),v.end(),x);
if (p!= v.end()) { /* ... */ }
}
void f(list<string>& v, string x) {
list<string>::iterator p = find(v.begin(),v.end(),x);
if (p != v.end()) { /* ... */ }
}
void f(set<double>& v, double x) {
set<double>::iterator p = find(v.begin,v.end(),x);
if (p != v.end()) { /* ... */ }
}
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
23
find_if() Algorithm Design
• Find the first element in the container that
matches a criterion
• Criterion is also general: let user specify what
it should be
– e.g., first element that is odd
• To do this, pass in as an argument a predicate
– function that returns either true or false
– e.g., whether or not current element is odd
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
24
find_if() Algorithm Code
template<class In, class Pred>
In find_if(In first, In last, Pred pred) {
while (first != last && !pred(*first))
++first;
return first;
}
// instantiating find_if
void f(vector<int>& v) {
vector<int>::iterator p =
find_if(v.begin(),v.end(),odd); // odd?
if (p != v.end()) { /* we found an odd number */ }
}
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
25
Predicate Function
• A function that returns a bool:
bool odd(int i) {
return i%2; // % is remainder operator;
// 0 = false, non-zero = true
}
• We pass in a function as an argument to
find_if(), like we saw for plotting functions
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
26
Limitations of Passing a Function
• Sometimes just passing a function as a
parameter isn’t good enough
• Suppose we need to also pass in a parameter
to the predicate function
– Example: find first element that is less than some
target value
– the less-than function is the predicate
– but we also need to pass in the target value (not
fixed in advance)
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
27
Defining Predicate Function Object
• Make a class that compares an object of any
type against any value (note genericity)
• We can store state in the class’ object
template<class T> struct Less_than {
T val; // value to compare against
Less_than(T& x) : val(x) { } // constructor
// overload function call operator:
bool operator()(const T& x) const {
return x < val;
}
};
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
28
Overloading Function Call Operator
• Suppose you’ve made an object of type
Less_than, call it lt.
– The constructor sets the data member “val” equal
to the constructor’s argument.
• You can then say “lt(x)”, which invokes
Less_than::operator() for object lt
– this function returns true if x is less than val, and
false otherwise.
• It is analogous to the way v[i] is shorthand for
vector::operator[]()
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
29
Using Predicate Function Object
template<class T> struct Less_than {
T val; // value to compare against
Less_than(T& x) : val(x) { } // constructor
// overload function call operator:
bool operator()(const T& x) const {
return x < val;
}
};
// find x < 43 in a vector of ints:
auto p = find_if(v.begin(),v.end(),Less_than(43));
// find x < “perfection” in a list of strings:
auto q =
find_if(ls.begin(),ls.end(),Less_than(“perfection”));
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
30
Function Objects
• Very efficient technique
– faster than equivalent function, even assuming
there is an equivalent function
• Main method of “policy parameterization” in
the STL
• Key to emulating functional programming
techniques in C++ (cf. CSCE 314)
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
31
Policy Parameterization
• For example, we need to parameterize sort()
by the comparison criterion
struct Record {
string name; // standard string for ease of use
char addr[24]; // old C-style string to match database
// ...
};
vector<Record> vr;
// ...
sort(vr.begin(),vr.end(),Cmp_byname()); // sort by name
sort(vr.begin(),vr.end(),Cmp_byaddr()); // sort by addr
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
32
Comparison for Name
struct Cmp_by_name{
// overload function call operator:
bool operator()(const Record& a,
const Record& b) const
{
return a.name < b.name; // use name field
}
};
// uses < which is defined for standard
// library string
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
33
Comparison for Address
struct Cmp_by_addr {
// overload function call operator:
bool operator()(const Record& a,
const Record& b) const
{
return 0 < strncmp(a.addr,b.addr,24);
// correct?
}
};
// comparison function (objects) hide ugly
// and error-prone code
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
34
Defining Policies with Lambda
Expressions
• Lambda expressions let you write short
functions “in line” without having to name the
functions
• Usually to pass as a parameter to another
function
• Syntax is to put “[ ]” where the return type
and name usually go
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
35
Defining Policies with Lambda
Expressions
vector<Record> vr;
// ...
sort(vr.begin(),vr.end(),
[](const Record& a, const Record& b)
{ return a.name < b.name; } // sort by name
);
sort(vr.begin(),vr.end(),
[](const Record& a, const Record& b)
{ return 0 < strncmp(a.addr,b.addr,24); }
// sort by address
);
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
36
Policy Parameterization Guidelines
• Use a named function object as argument
– to do something complicated
– if you want to do the same in several places
• Use a lambda expression as argument
– if what you want is short and obvious
• Decide based on clarity of code
– there are no performance differences between
function objects and lambdas
– both tend to be faster than function arguments
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
37
Vector and List Implementations
• Let’s peek inside vector and list
implementation focusing on iterators and
more functions
• Topics:
– what type is a vector/list iterator?
– begin and end functions
– erase function (remove an element)
– insert function (add a function anywhere)
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
38
vector Implementation
template<class T> class vector {
T* elements;
// ...
using iterator = ???;
// type of an iterator is implementation-defined
// and it varies; a vector iterator could be a
// pointer to an element. “using” is the same as
// typedef – gives convenient name to the type
iterator begin(); // points to first element
iterator end(); // points to one past last element
iterator erase(iterator p);
// remove element pointed to by p
iterator insert(iterator p, const T& v);
// insert new element v before element pointed to by p
};
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
39
insert() into vector
• Shift down all the array elements after the
indicated location and then put new element
in that location
• Warning! If you have other iterators that refer
to elements of the vector, they are now invalid
– some, and perhaps all, of the elements have
moved so their addresses have changed
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
40
vector insert() Example
vector<int>::iterator p = v.begin(); ++p; ++p; ++p;
vector<int>::iterator q = p; ++q;
q:
v:
6
p:
0
1
p = v.insert(p,99);
v:
2
3
4
5
q:
p:
7
0
1
2
99
3
4
5
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
41
erase() from vector
• Shift up all the array elements starting at the
indicated location to close up the “hole”
• Warning! If you have other iterators that refer
to elements of the vector, they are now invalid
– some, and perhaps all, of the elements have
moved so their addresses have changed
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
42
vector erase() Example
• Continuing the previous example:
q:
p:
v:
7
0
1
2
p = v.erase(p);
v:
99
3
4
5
q:
p:
6
0
1
2
3
4
5
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
43
list Implementation
Link:
T value
template<class T> class list {
Link* prev
Link* elements;
Link* succ
// ...
using iterator = ???;
// type of an iterator is implementation-defined
// and it varies; a list iterator could be a
// pointer to a link node. “using” is the same as
// typedef – gives convenient name to the type
iterator begin(); // points to first element
iterator end(); // points to one past last element
iterator erase(iterator p);
// remove element pointed to by p
iterator insert(iterator p, const T& v);
// insert new element v before element pointed to by p
};
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
44
insert() and erase() for list
• Since we have a linked list, we can insert and
erase from the list without disturbing the
locations of the other elements
• Manipulate the pointers in the Link nodes
appropriately to splice in or out the relevant
Link node
• Other iterators that point to list elements are
NOT invalidated for the list container
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
45
list insert() Example
list<int>::iterator p = v.begin(); ++p; ++p; ++p;
list<int>::iterator q = p; ++q;
v:
6
0
1
v = v.insert(p,99);
v:
q:
p:
2
3
p:
4
5
q:
7
0
1
2
CSCE 121:509-512 Set 19:
99
The STL: Containers and Iterators
3
4
5
46
list erase() Example
p:
v:
q:
7
0
1
2
3
4
5
99
p = v.erase(p);
v:
q:
p:
6
0
1
2
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
3
4
5
47
Ways of Traversing a Vector
for (int i = 0; i < v.size(); ++i)
// do something with v[i]
// why int?
for (vector<T>::size_type i = 0; i < v.size(); ++i)
// do something with v[i]
// longer but always correct
for (vector<T>::iterator p = v.begin();
p != v.end(); ++p)
// do something with *p
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
48
Subscript vs. Iterator Vector Traversals
•
•
•
•
subscript style is used in essentially every language
iterator style is used in C (pointers only) and C++
iterator style is used for standard library algorithms
subscript style does not work for lists (in C++ and in
most languages)
• iterator style works for all containers
• use subscript style if you need to know the index
• prefer size_type over plain int (pendantic but quiets
compiler and prevents rare errors)
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
49
Another Way of Traversing a Vector:
Range For
for (vector<T>::value_type x : v)
// do something with x;
// assumes vector implementation includes
// “using value_type T;”
for (auto& x : v)
// do something with x
•Use “range for” in this situation:
–
–
–
–
very simple loop
over a single sequence
you don’t need to access more than one element at a time
you don’t need to know the position of the current element
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
50
Vector vs. List
• By default, use vector
– provides push_back, insert, erase and more
– elements are stored compactly and contiguously
• If you don’t want elements to move, use a list
– provides push_back, push_front, insert, erase and
more
– elements are independently allocated
• More containers coming up in next lecture...
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
51
Some Useful Standard Headers
•
•
•
•
•
•
•
<algorithm> sort, copy, ...
<numeric> accumulate, ...
<functional> function objects
<string>
<vector>
<list>
<map>, <unordered_map>, <set> coming up
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
52
More on the STL
• Designed by Alex Stepanov
• Goal: most general, efficient, and
flexible representation of
concepts (algorithms
– represent separate concepts with
separate code
– combine concepts
• Make programming “like math”
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
53
STL by the Numbers
• ISO C++ standard framework has about 10
containers and about 60 algorithms connected
by iterators
• Other organizations provide more containers
and algorithms in the style of the STL
– Boost.org, Microsoft, SGI,…
• Probably the currently best known and most
widely used example of generic programming
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
54
STL References
• If you know the basic concepts and a few examples,
you can use the rest
• Documentation
– SGI
• http://www.sgi.com/tech/stl/ (recommended because of clarity)
– Dinkumware
• http://www.dinkumware.com/refxcpp.html (beware of several
library versions)
– Rogue Wave
• http://www.roguewave.com/support/docs/sourcepro/stdlibug/ind
ex.html
• More accessible and less complete documentation
– Appendix B
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
55
Acknowledgments
• Photo on title slide: Dakar Baskets by Carrie
Cizauskas, license CC BY-NC-ND 2.0
• Slides are based on those for the textbook:
http://www.stroustrup.com/Programming/20_vector.ppt
CSCE 121:509-512 Set 19:
The STL: Containers and Iterators
56