This chapter covered iterators, list containers, and new functions for strings, vectors, and lists.
As before, I’m just going to post an unordered list of definitions, jargon, types and functions, etc.
const references passed to the function when called.vector.push_back(x)x value to end of container.vector.erase(vector.begin() + i)i. The parameter within the parentheses is an element value, not the index of the value. Note that erasing also lessens the number of elements by 1, so for loop iterations where you erase() you must not increase the counting variable so that the invariant remains true.vector.size() must be called for each iteration(for example, inside of the while condition), for a fresh count of the number of elements.“The reason we care about the sequence in which we access container elements is that different types of containers have different performance characteristics and support different operations. If we know that our program uses only those operations that a particular type of container supports efficiently, then we can make our program more efficient by using that kind of container.” (Koenig & Moo, 79)
“…identifies a container and an element in the container …lets us examine the value stores in that element …provides operations for moving between elements in the container …restricts the available operations in ways that correspond to what the container can handle efficiently.” (Koenig & Moo, 80)
iterator and const_iteratoriterator allows modification of elements, and const_iterator type only allows reading of elements. Type is written as vector<double>::const_iterator, for example.vector.begin().begin() or .end() actually return an iterator type value. Authors tell there is also an automatic one-way conversion between values of type iterator and type const iterator—less overhead for the developer. Being able to compare the iterator to .end() is great, because it means that we do not have to compute an i index any longer—one less step, and much more intuitive. Abstraction is great.++iter++ operator is overloaded for the iterator type, so that it means to increment sequentially…* operatoriterator is a weird value that is quasi-index and quasi-reference to a specific value… To read the specific value(or access for writing), it is necessary to use the dereference operator: if ( (*iter).name == "Patrick" ) { ... } Note: * is lower precedence than other operations, and may need to be enclosed within parentheses.(*iter).memberName; you may use the -> syntax: iter->memberName. Cool.Aside: I’m glad I have some background in scripting and programming, working with containers, etc, because the exercises in this book don’t do some of these types justice… whereas I can think of ways I could have implemented my past-written programs differently using new stuff from this book.
.erase() invalidates…vector.erase(iter) invalidates all iterators at that element and beyond… Therefore, even if you precompute an iterator for the value 10 elements deeper in the container, or an iterator for the last value in the list, it will vanish when you call .erase(). The function returns the iterator positioned on the immediate sequential value, however. iter = vector.erase(iter) yields the value of the iter + 1…list type“Just as
vectors are optimzied for fast random access,lists are optimized for fast insertion and deleetion anywhere within the container. …if a program deletes many elements from the middle of the container, thenlists will be fsater for large inputs [thanvectors].” (Koenig & Moo 85)
vectors and lists are examples of templates, declared with the type they use, like so: vector<double>.<algorithm>-defined function works on vectors but not lists?<algorithm>-defined sort() function does not work on list containers. And I was building the chapter exercise well before the author detailed this fact—so I had to troubleshoot why my program was no longer compiling.. The list class has its own member function to .sort() values.lists or vectors for students’ records. For a small size of 735 records, each choice of container type ran in 0.1 seconds. But for larger amounts of records:“For the file with 73,500 records, the
listversion of the program took less than nine seconds to run, whereas thevectorversion took nearly ten minutes.”
strings also work like containersisspace( char )<cctype>. This predicate takes a char and returns true for whitespace values and false for anything else.&& and || are operators that test the left operand first, and short-circuit as soon as the first false condition arises… a consideration for better performance, I imagine.stringName.substr(i, len)substr() of the string class takes an index and a length, and returns a new string of the given argument.getline(istreamName, stringName)getline() function is defined in <string> and is useful for grabbing a whole line of input, including whitespace; the more common cin parses out whitespace… getline returns an istream reference, as cin does, and therefore can be used as a condition in a statement(as all istreams can).+=list[indexVar++]++ after the indexVar, it is incremented only after the existing value is passed as the index… or likewise, for when the operation is used in other places.newStringName = string(stringSizeVar, ' ')string() function takes the string size(a special data type) and a character literal, and creates a new string that long and with that character…container.rbegin() and container.rend()vector<double> doppelganger(original)doppelganger which is a copy of the existing vector original.container<type> name(155)container<type> name(155, otherVar)otherVar.container<type> name(b, e)b and e are existing iterators for an identical-type container that already exists. This will create a new container with the elements copied from the other existing container between iterators b and e.containerName.empty()container.insert(d, b, e)[b, e) and inserts them into the container just before iterator(?) d.container.erase(iter) or container.erase(b, e)iter or erases the elements in range [b, e).*iter*, passes the value stored at the position of the iterator. As noted above, this is frequently used for class objects, and a special operator exists: iter->memberName is the same as (*iter).memberName.vectorName.reserve(n)n elements. It does not affect the computable number of elements in the container; for example, vectorName.size() would still yield the actual number of elements, and not n unless they were coincidentally the same value.vectorName.resize(n)n, and truncates any exceeding elements, or adds sufficient new elements initialized to the appropriate/default value defined by the class.isalpha(char)<cctype>.isdigit(char)<cctype>.isalnum(char)<cctype>.ispunct(char)<cctype>.isupper(char)<cctype>.islower(char)<cctype>.toupper(c)c. Defined in <cctype>.tolower(c)c. Defined in <cctype>.That chapter took me awhile.