Professional C__ - Marc Gregoire [238]
Chapter 17 describes how to use iterator adapters to insert elements into a container or stream with copy().
Here is a simple example of copy() that uses the resize() method on vectors to ensure that there is enough space in the destination container. It copies all elements from vec1 to vec2:
// The populateContainer() function is identical to the one shown earlier
// for comparison algorithms, so it is omitted here.
vector populateContainer(vec1); vec2.resize(vec1.size()); copy(vec1.cbegin(), vec1.cend(), vec2.begin()); for_each(vec2.cbegin(), vec2.cend(), [](int i){cout << i << " ";}); Code snippet from ModifyingAlgorithms\Copy.cpp There is also a copy_backward() algorithm, which copies the elements from the source backward to the destination. In other words, it starts with the last element of the source and puts it in the last position in the destination range and moves backward after each copy. The preceding example can be modified to use copy_backward() instead of copy() as follows. Note that you need to specify vec2.end() as third argument instead of vec2.begin(): copy_backward(vec1.cbegin(), vec1.cend(), vec2.end()); Code snippet from ModifyingAlgorithms\copy_backward.cpp This will result in exactly the same output. C++11 adds a few new copy algorithms. These include conditional copy, copy of a specified number of elements (so instead of specifying an ending iterator, only a count is necessary), and a copy that can copy to two different destinations. The first one is copy_if(). It works by having an input range specified by two iterators, an output destination specified by an iterator, and a predicate (function or lambda expression). The function or lambda expression is executed for each element that is a candidate to be copied. If the returned value is true, the element is copied and the destination iterator is incremented; if the value is false the element is not copied and the destination iterator is not incremented. Thus, the destination may hold fewer elements than the source range. For some containers, because they must have already created space to hold the maximum possible number of elements (remember, copy does not create or extend containers, merely replaces the existing elements), it might be desirable to remove the space “beyond” where the last element was copied to. To facilitate this, copy_if() returns an iterator to the one-past-the-last-copied element in the destination range. This can be used to determine how many elements should be removed from the destination container. The following example demonstrates this by copying only the even numbers to vec2: // The populateContainer() function is identical to the one shown earlier // for comparison algorithms, so it is omitted here. vector populateContainer(vec1); vec2.resize(vec1.size()); auto endIterator = copy_if(vec1.cbegin(), vec1.cend(), vec2.begin(), [](int i){return i%2==0;}); vec2.erase(endIterator, vec2.end()); for_each(vec2.cbegin(), vec2.cend(), [](int i){cout << i << " ";}); Code snippet from ModifyingAlgorithms\copy_if.cpp Another C++11 addition is copy_n(), which copies n elements from the source to the destination. The first parameter of copy_n() is the start iterator. The second parameter of copy_n() is an integer specifying the number of elements to copy and the third parameter is the destination iterator. The copy_n() algorithm does not perform any bounds checking, so you must make sure that the start iterator, incremented by the number of elements to copy, does not exceed the end() of the collection or your program will have undefined behavior. Following is an example: // The populateContainer() function is identical to the one shown earlier // for comparison algorithms, so it is omitted here. vector populateContainer(vec1);