Introduction
There are far more things in the C++ Standard Library than we have time to cover. We will limit ourselves to looking at some of the most commonly used features that we haven’t yet explored.
Iterators
Iterators serve the same purpose as IEnumerable
and related interfaces in .NET, such as providing a common way to navigate through collections. Given a std::vector
, for example, you can loop through its collection of items using the following code:
vector<int> vec; vec.push_back(1); vec.push_back(4); vec.push_back(7); vec.push_back(12); vec.push_back(8); for (auto i = begin(vec); i != end(vec); i++) { wcout << *i << endl; }
The std::begin
function provides an iterator pointing to the first item of the collection. std::end
provides an iterator that signals we have reached the end of a collection; the last item of the collection, assuming the collection has any items, is one item before the item we are given by std::end
. That’s why we check for != in the for loop. If no items are in the collection, then std::begin
and std::end
will return the same value.
In addition to the iterators from those two template functions, many collections provide const iterators via member functions named cbegin and cend, reverse iterators (that loop through a collection backwards) via rbegin
and rend
, and const reverse iterators via crbegin
and crend
. In the previous example, you can replace begin(vec)
with vec.rbegin()
and end(vec)
with vec.rend()
to go through the vector in reverse.
Range-Based for Loops
C++11 has added an additional type of for loop, called the range-based for loop, which provides functionality similar to the foreach loop in C#. The range-based for loop uses iterators and saves you the trouble of de-referencing pointers and the possibility of improperly checking for the end. The range-based for loop equivalent to the for loop in the previous example looks like this:
for (auto item : vec) { wcout << item << endl; }
std::vector
and Other Containers
The collection you are likely to use most is std::vector
. It is a fast, general-purpose collection similar to List<T> in .NET. It is found in the <vector> header file.
To add an item to the end of a vector, use the member function push_back
. To remove an item from the end of a vector, use pop_back
. You can access items at their index using [] the same way you would an array. To add an element or range of elements at a specific zero-based index, use the insert member function. To remove an element or range of elements at a specific zero-based index, use the erase member function.
A neat feature added in C++11 is the in-place construction functionality provided by the emplace and emplace_back member functions. Rather than constructing an object and then using insert or push_back to add it to the vector, you can call emplace_back and simply pass it the same arguments you would pass to the constructor for the type that the vector is holding. The vector will then construct and add a new instance of the object without the extra calculations that come with a copy or a move, and without using extra local memory.
The emplace
function works the same, except you start by passing it an iterator that specifies the location. You can use cbegin()
or cend()
to add items to the beginning or end of the vector. If you have a specific zero-based index you want to emplace an item at, you can use vec.cbegin() + idx
. You can also subtract from cend()
if you want to place an item some number of spaces from the end.
vector offers more functionality, so you should definitely explore it further. The at member function will give you an item at an index, for example. There are ways to tell the vector to resize its internal capacity so you have more room free—if you knew you would need exactly 125 items, for instance—or so you minimize memory usage—if you added all the elements it will ever need and memory constraints are tight.
In addition to std::vector
, several similar containers have different use cases. std::vector
itself is the best choice when you need extremely fast, random access—when you will mostly be adding items to and removing items from the very end of the collection. If you also need to add items frequently to the front of the collection, you should consider using std::deque
instead.
Use std::queue
for a first-in, first-out container. Use std::stack for a last-in, first-out container.
The std::map
class provides a sorted dictionary. std::unordered_map
provides a hash table.
The std::set
class is a sorted, keyed collection where the item stored is its own key, so each element must be unique. std::unordered_set
is the unsorted equivalent of std::set
.
The std::list
class provides a doubly linked list. std::forward_list
provides a singly linked list.
The <algorithm>
Header
The <algorithm> header contains many very useful functions: things such as find, sort, copy, and all their related methods. The best way to learn them is to experiment with them.
The C Run-Time Library (CRT)
Some functionality from the C Runtime Library can be useful. Generally, the best way to access the library is to include the relevant <c_____> header file, such as <cstdlib>.
Conclusion
The C++ Standard Library has a lot more to offer so I highly recommend exploring it and getting familiar with it. In the final article of this series, we explore Visual Studio and how it's best used for C++ development.
This lesson represents a chapter from C++ Succinctly, a free eBook from the team at Syncfusion.
Comments