Online Book Reader

Home Category

Professional C__ - Marc Gregoire [190]

By Root 1434 0
Containers that allow you to iterate over its elements in reverse order also provide public typedefs called reverse_iterator and const_reverse_iterator. This way, clients can use the container iterators without worrying about the actual types.

const_iterators and const_reverse_iterators provide read-only access to elements of the container.

The containers also provide a method begin() that returns an iterator referring to the first element in the container. The end() method returns a reference to the “past-the-end” value of the sequence of elements. That is, end() returns an iterator that is equal to the result of applying operator++ to an iterator referring to the last element in the sequence. Together begin() and end() provide a half-open range that includes the first element but not the last. The reason for this apparent complication is to support empty ranges (containers without any elements), in which case begin() is equal to end(). The half-open range bounded by iterators begin() and end() is often written mathematically like this: [begin,end).

Similarly, there are rbegin() and rend() methods for working with reverse iterators.

The half-open range concept also applies to iterator ranges that are passed to container methods such as insert() and erase(). See the specific container descriptions later in this chapter for details.

C++11 Changes

C++11 introduces several changes to the STL containers. One change is the introduction of the unordered associative containers, also called hash tables, which are discussed later in this chapter.

Other changes are performance related. All STL containers now implement move semantics by including a move constructor and move assignment operator. These use rvalue references as described in Chapter 9. A big benefit of this is that we can easily return an STL container from a function by value without performance degradation. Take a look at the following function:

vector createVectorOfSize(size_t size)

{

vector vec(size);

int contents = 0;

for (auto& i : vec)

i = contents++;

return vec;

}

Code snippet from CreateVectorOfSize\CreateVectorOfSize.cpp

Without move semantics, the preceding function will create a local vector called vec. The return statement will then make a copy of vec and return it from the function. With the C++11 move semantics support in the STL containers, this copying of the vector is avoided. Instead, the return statement will move the vector. Moving is possible in this case because vec will go out of scope.

Similarly, push operations can also make use of move semantics to improve performance in certain situations. For example, suppose you have a vector of elements of type Element as follows:

class Element

{

public:

Element(int i, string str) : mI(i), mStr(str) {}

protected:

int mI;

string mStr;

};

int main()

{

vector vec;

return 0;

}

Code snippet from MovePushBack\MovePushBack.cpp

Adding an element to this vector can be done as follows:

Element myElement(12, "Twelve");

vec.push_back(myElement);

Code snippet from MovePushBack\MovePushBack.cpp

However, since myElement is not a temporary object, the push_back() call will make a copy of myElement and put it in the vector. This copying can be avoided if you call the push_back() method as follows:

vec.push_back(Element(12, "Twelve"));

Code snippet from MovePushBack\MovePushBack.cpp

The vector class defines a push_back(T&& val) which is the move equivalent of push_back(const T& val). The preceding call to vec.push_back() will trigger a call to the move version because the call to the Element constructor results in a temporary object. The push_back() method will move this temporary Element object into the vector, avoiding any copying.

Using C++11 uniform initialization (Chapter 9), the preceding can also be written as follows:

vec.push_back({12, "Twelve"});

Code snippet from MovePushBack\MovePushBack.cpp

In addition, C++11 adds support for emplace operations on most STL containers. Emplace means “to put into place.” An example is emplace_back()

Return Main Page Previous Page Next Page

®Online Book Reader