Professional C__ - Marc Gregoire [240]
Move operator= (mStr=c)
a b c
Chapter 9 explains that source objects in a move operation are reset because the target object takes ownership of the resources of the source object. For the previous example, this means that you should not use the objects from vecSrc anymore after the move operation.
move_backward() uses the same move mechanism as move() but it moves the elements from the last to the first element.
replace
The replace() and replace_if() algorithms replace elements in a range matching a value or predicate, respectively, with a new value. Take replace_if() as an example. Its first and second parameters specify the range of elements in your container. The third parameter is a function or lambda expression that returns true or false. If it returns true, the value in the container is replaced with the value given as fourth parameter; if it returns false, it leaves the original value.
For example, you might want to replace all values less than a lower limit with the value of the lower limit and replace all values greater than an upper limit with the value of the upper limit. This is called “clamping” values to a range. In audio applications, this is known as “clipping”. For example, audio signals are often limited to integers in the range of -32K to +32K. The following example demonstrates this by first calling replace_if() to replace all values less than -32K with -32K and then calling a second replace_if() to replace all values greater than 32K with 32K:
// The populateContainer() function is identical to the one shown earlier
// for comparison algorithms, so it is omitted here.
vector populateContainer(vec); int lowLim = numeric_limits int upLim = numeric_limits replace_if(vec.begin(), vec.end(), [=](int i){return i < lowLim;}, lowLim); replace_if(vec.begin(), vec.end(), [=](int i){return i > upLim;}, upLim); for_each(vec.cbegin(), vec.cend(), [](int i){cout << i << " ";}); Code snippet from ModifyingAlgorithms\Replace.cpp There are also variants of replace() called replace_copy() and replace_copy_if() that copy the results to a different destination range. remove Suppose you have a range of elements and you want to remove elements matching a certain condition. The first solution that you might think of is to check the documentation to see if your container has an erase() method and then iterate over all the elements and call erase() for each element that matches the condition. The vector is an example of a container that has such an erase() method. However, if applied to the vector container, this solution is very inefficient as it will cause a lot of memory operations to keep the vector contiguous in memory, resulting in a quadratic complexity (see Chapter 2), which is very bad. This solution is also error-prone, because you need to be careful that you keep your iterators valid after a call to erase(). The correct solution for this problem is the so-called remove-erase-idiom, which runs in linear time and is explained in this section. The remove() and remove_if() algorithms “remove” certain elements from a range by partitioning the collection into two sets: the elements to be kept and the elements to be removed. The elements to remove can be specified by either a specific value or with a predicate. These elements are not really removed from the underlying container, because the algorithms have access only to the iterator abstraction, not to the container. Instead, elements to be kept are moved or copied to the beginning of the range and elements to be removed are moved or copied to the end of the range. An iterator is returned that points to the first element in the range of elements to be removed. If you want to actually erase these elements from the container, you must use the remove() algorithm, then call erase() on the container to erase all the elements from the returned iterator up to the end of the range. This is the remove-erase-idiom. Here is an example of a function that removes empty strings from a vector