Professional C__ - Marc Gregoire [292]
// Chapter 13, so it is omitted here.
vector set populateContainer(vectorOne); insert_iterator remove_copy_if(vectorOne.begin(), vectorOne.end(), inserter, [](int i){return i==100;}); copy(setOne.begin(), setOne.end(), ostream_iterator Code snippet from IteratorAdapters\InsertIterator.cpp Note that the insert_iterator modifies the iterator position hint that it passes to insert() after each call to insert(), such that the position is one past the just-inserted element. Move Iterators Chapter 9 discusses a new C++11 feature called move semantics, which can be used to prevent unnecessary copying in cases where you know that the source object will be destroyed after an assignment or copy construction. C++11 also introduces a move_iterator. The dereferencing operator for a move_iterator will automatically convert the value to an rvalue reference, which means that the value can be moved to a new destination without the overhead of copying. Before you can use move semantics, you need to make sure your objects are supporting it. The following MoveableClass supports move semantics. For more details, see Chapter 9. class MoveableClass { public: MoveableClass() { cout << "Default constructor" << endl; } MoveableClass(const MoveableClass& src) { cout << "Copy constructor" << endl; } MoveableClass(MoveableClass&& src) { cout << "Move constructor" << endl; } MoveableClass& operator=(const MoveableClass& rhs) { cout << "Copy assignment operator" << endl; return *this; } MoveableClass& operator=(MoveableClass&& rhs) { cout << "Move assignment operator" << endl; return *this; } }; Code snippet from IteratorAdapters\MoveIterators.cpp The constructors and assignment operators are not doing anything useful here, except printing a message to make it easy to see which one is being called. Now that you have this class, you can define a vector and store a few MoveableClass instances in it as follows: vector MoveableClass mc; vecSource.push_back(mc); vecSource.push_back(mc); Code snippet from IteratorAdapters\MoveIterators.cpp The second line of the code creates a MoveableClass instance by using the default constructor. The first push_back() call triggers the copy constructor to copy mc into the vector. After this operation, the vector will have space for one element, the first copy of mc. The second push_back() call triggers the vector to resize itself, to allocate space for the second element. This resizing causes the move constructor to be called to move every element from the old vector to the new resized vector. After that, the copy constructor is triggered to copy mc a second time into the vector. The output should be as follows: Default constructor Copy constructor Move constructor Copy constructor You can create a new vector called vecOne that contains a copy of the elements from vecSource as follows: vector Without using move_iterators, this code triggers the copy constructor two times, once for every element in vecSource: Copy constructor Copy constructor By using the make_move_iterator() function to create move_iterators, the move constructor of MoveableClass is called instead of the copy constructor: vector make_move_iterator(vecSource.end())); This generates the following output: Move constructor Move constructor Once objects have been moved, you should not access the original objects anymore. For example, in the previous example, you should not access objects in vecSource after having moved them to vecTwo. See Chapter 9 for details on move semantics. EXTENDING THE STL
The STL includes many useful containers, algorithms, and iterators that you can use in your applications. It is impossible, however, for any library to include all possible utilities that all potential clients might