5.2 Standard Template Library (STL) : Tandard I Brary
5.2 Standard Template Library (STL) : Tandard I Brary
a compile-time error. In C99, <stdint.h> may define the types intptr_h and
uintptr_h.
Conventions for "Structured" TMP
14
14
15
16
H T T P :// E N . W I K I B O O K S . O R G / W I K I /C A T E G O R Y %3AC%2B%2B%20P R O G R A M M I N G
Chapter 3.1.2 on page 45
H T T P :// E N . W I K I B O O K S . O R G / W I K I /%23C O N T A I N E R S
499
Advanced Features
5.2.1 History
The C++ Standard Library incorporated part of the STL (published as a software
library by SGI17 /Hewlett-Packard Company). The primary implementer of the
C++ Standard Template Library was A LEXANDER S TEPANOV18 .
Today we call STL to what was adopted into the C++ Standard. The ISO C++
does not specify header content, and allows implementation of the STL either in
the headers, or in a true library.
17
18
500
H T T P :// E N . W I K I P E D I A . O R G / W I K I /S I L I C O N %20G R A P H I C S
H T T P :// E N . W I K I P E D I A . O R G / W I K I /A L E X A N D E R %20S T E P A N O V
Note:
In an interview Alexander Stepanov, stated that he originally, wanted all auxiliary functions in STL to be visible but it was not politically possible, especially
the heap functions. That Bjarne did reduce the number of components in STL
by a factor of two as to permit the adoption into the standard.
Compilers will already have one implementation included as part of the C++ Standard (i.e., MS Visual Studio uses the Dinkum STL). All implementations will have
to comply to the standards requirements regarding functionality and behavior, but
consistency of programs across all major hardware implementations, operating
systems, and compilers will also depends on the portability of the STL implementation. They may also offer extended features or be optimized to distinct setups.
List of STL implementations.
Apache C++ Standard Library (STDCXX) ( HTTP :// STDCXX . APACHE . ORG /22
).
19
20
21
22
H T T P :// W W W . S G I . C O M / T E C H / S T L /)
H T T P :// E N . W I K I P E D I A . O R G / W I K I /A P A C H E %20C%2B%2B%20S T A N D A R D %
20L I B R A R Y
H T T P :// W W W . D I N K U M W A R E . C O M /)
H T T P :// S T D C X X . A P A C H E . O R G /
501
Advanced Features
STLport STL library (HTTP :// WWW. STLPORT. COM /)23 free and highly crossplatform implementation based on the SGI implementation.
Note:
There are advantages on having compartmentalized functionalities, some developers actively avoid using some of the language features, for a multitude of
reasons. C++ permits the programmer to chose how to express himself, have
control over the development paradigms and not be constricted by an higher
level of abstraction.
5.2.2 Containers
The containers we will discuss in this section of the book are part of the standard
namespace (std::). They all originated in the original SGI implementation of the
STL.
Note:
When choosing a container, you should have in mind what makes them different, this will help you produce more efficient code. See also the O PTIMIZA TION S ECTION a of the book, about USING THE RIGHT DATA IN THE RIGHT
CONTAINER b .
a
b
Sequence Containers
Sequences - easier than arrays
Sequences are similar to C arrays, but they are easier to use. Vector is usually
the first sequence to be learned. Other sequences, list and double-ended queues,
are similar to vector but more efficient in some special cases. (Their behavior is
also different in important ways concerning validity of iterators when the container
is changed; iterator validity is an important, though somewhat advanced, concept
when using containers in C++.)
23
502
H T T P :// W W W . S T L P O R T . C O M /)
24
H T T P :// E N . W I K I P E D I A . O R G / W I K I / D Y N A M I C %20 A R R A Y
503
Advanced Features
Note:
If you create a vector you can access its data using consecutive pointers:
std::vector<type> myvector(8); type * ptr = myvector[0]; ptr[0],
ptr[7]; // access the first and last objects in myvector
/*
David Cary 2009-03-04
quick demo for wikibooks
*/
#include <iostream>
#include <vector>
using namespace std;
vector<int> pick_vector_with_biggest_fifth_element(vector<int> left,vector<int>
right)
{
if(left[5] < right[5])
{
return( right );
}
// else
return left ;
}
int* pick_array_with_biggest_fifth_element(int * left,int * right)
{
if(left[5] < right[5])
{
return( right );
}
// else
return left ;
}
504
int vector_demo(void)
{
cout << "vector demo" << endl;
vector<int> left(7);
vector<int> right(7);
left[5] = 7;
right[5] = 8;
cout << left[5] << endl;
cout << right[5] << endl;
vector<int> biggest(pick_vector_with_biggest_fifth_element( left, right ) );
cout << biggest[5] << endl;
return 0;
}
int array_demo(void)
{
cout << "array demo" << endl;
int left[7];
int right[7];
left[5] = 7;
right[5] = 8;
cout << left[5] << endl;
cout << right[5] << endl;
int * biggest =
pick_array_with_biggest_fifth_element( left, right );
cout << biggest[5] << endl;
return 0;
}
int main(void)
{
vector_demo();
array_demo();
}
Member Functions
The vector class models the C ONTAINER25 CONCEPT26 , which means it has
begin(), end(), size(), max_size(), empty(), and swap() methods.
25
26
H T T P :// W W W . S G I . C O M / T E C H / S T L /C O N T A I N E R . H T M L
H T T P :// E N . W I K I P E D I A . O R G / W I K I / C O N C E P T %20%28 G E N E R I C %
20 P R O G R A M M I N G %29
505
Advanced Features
Note:
Since most vector (or deque) implementations typically reserves some extra
internal storage for future growth. Prefer the swap() method when altering
a standard vector size (or freeing the memory used) when memory resources
becomes a factor.
informative
vector::front - Returns reference to first element of vector.
vector::back - Returns reference to last element of vector.
vector::size - Returns number of elements in the vector.
vector::empty - Returns true if vector has no elements.
standard operations
vector::insert - Inserts elements into a vector (single & range), shifts later
elements up. Inefficient.
vector::push_back - Appends (inserts) an element to the end of a vector,
allocating memory for it if necessary. A MORTIZED27 O(1) time.
vector::erase - Deletes elements from a vector (single & range), shifts later
elements down. Inefficient.
vector::pop_back - Erases the last element of the vector, (possibly reducing
capacity - usually it isnt reduced, but this depends on particular STL implementation). A MORTIZED28 O(1) time.
vector::clear - Erases all of the elements. Note however that if the data
elements are pointers to memory that was created dynamically (e.g., the new
operator was used), the memory will not be freed.
allocation/size modification
vector::assign - Used to delete a origin vector and copies the specified
elements to an empty target vector.
vector::reserve - Changes capacity (allocates more memory) of vector, if
needed. In many STL implementations capacity can only grow, and is never
reduced.
vector::capacity - Returns current capacity (allocated memory) of vector.
vector::resize - Changes the vector size.
iteration
vector::begin - Returns an iterator to start traversal of the vector.
vector::end - Returns an iterator that points just beyond the end of the vector.
vector::at - Returns a reference to the data element at the specified location
in the vector, with bounds checking.
27
28
506
H T T P :// E N . W I K I P E D I A . O R G / W I K I /A M O R T I Z E D %20 A N A L Y S I S
H T T P :// E N . W I K I P E D I A . O R G / W I K I /A M O R T I Z E D %20 A N A L Y S I S
Note:
It is important to remember the distinctions of capacity(), size() and empty()
when dealing with containers.
vector<int> v;
for (vector<int>::iterator it = v.begin(); it!=v.end(); ++it/* increment operand
is used to move to next element*/) {
cout << *it << endl;
}
vector::Iterators
std::vector<T> provides Random Access Iterators; as with all containers, the
primary access to iterators is via begin() and end() member functions. These
are overloaded for const- and non-const containers, returning iterators of types
std::vector<T>::const_iterator and std::vector<T>::iterator respectively.
vector examples
507
Advanced Features
The call to sort above actually calls an instantiation of the function template
std::sort, which will work on any half-open range specified by two random
access iterators.
If you like to make the code above more "STLish" you can write this program in
the following way:
#include
#include
#include
#include
<iostream>
<vector>
<algorithm>
<iterator>
int main()
{
using namespace std;
cout << "Sorting STL vector, \"the easier array\"... " << endl;
cout << "Enter numbers, one per line. Press ctrl-D to quit." << endl;
vector<int> vec(istream_iterator<int>(cin), istream_iterator<int>());
sort(vec.begin(), vec.end());
cout << "Sorted: " << endl;
copy(vec.begin(), vec.end(), ostream_iterator<int>(cout, "\n"));
return 0;
}
Linked lists
The STL provides a class template called list (part of the standard namespace
(std::)) which implements a non-intrusive doubly-LINKED LIST29 . Linked lists can
insert or remove elements in the middle in constant time, but do not have random
access. One useful feature of std::list is that references, pointers and iterators to
items inserted into a list remain valid so long as that item remains in the list.
Note:
Consider using vector instead of list for better cache coherency and avoid
"death by swapping", see the O PTIMIZATION S ECTIONa , about using the
RIGHT DATA IN THE RIGHT CONTAINER b .
a
b
29
H T T P :// E N . W I K I P E D I A . O R G / W I K I / L I N K E D %20 L I S T
508
*/
509
Advanced Features
string alphabet("abcdefghijklmnopqrstuvwxyz");
for (string::iterator letter_index=alphabet.begin(); letter_index !=
alphabet.end(); letter_index++) {
if (chars[*letter_index] != 0) {
cout << char(toupper(*letter_index))
<< ":" << chars[*letter_index]
<< "\t" << endl;
}
}
return 0;
}
Container Adapters
stack - last in, first out (LIFO)
queue - first in, first out (FIFO)
priority queue
5.2.3 Iterators
C++s iterators are one of the foundation of the STL. Iterators exist in languages
other than C++, but C++ uses an unusual form of iterators, with pros and cons.
In C++, an iterator is a concept rather than a specific type, they are a generalization
of the pointers as an abstraction for the use of containers. Iterators are further
divided based on properties such as traversal properties.
The basic idea of an iterator is to provide a way to navigate over some collection
of objects concept.
Some (overlapping) categories of iterators are:
Singular iterators
Invalid iterators
Random access iterators
Bidirectional iterators
Forward iterators
Input iterators
Output iterators
Mutable iterators
510
Note the usage of typename. It informs the compiler that const_iterator is a type
as opposed to a static member variable. (It is only necessary inside templated code,
and indeed in C++98 is invalid in regular, non-template, code. This may change
in the next revision of the C++ standard so that the typename above is always
permitted.)
Modifying each element of a container group of type C<T> using an iterator.
for (
typename C<T>::iterator iter = group.begin();
iter != group.end();
++iter
)
30
511
Advanced Features
{
T &element = *iter;
// modify element here
}
When modifying the container itself while iterating over it, some containers (such
as vector) require care that the iterator doesnt become invalidated, and end up
pointing to an invalid element. For example, instead of:
for (i = v.begin(); i != v.end(); ++i) {
...
if (erase_required) {
v.erase(i);
}
}
Do:
for (i = v.begin(); i != v.end(); ) {
...
if (erase_required) {
i = v.erase(i);
} else {
++i;
}
}
The erase() member function returns the next valid iterator, or end(), thus ending the loop. Note that ++i is not executed when erase() has been called on an
element.
5.2.4 Functors
A functor or function object, is an object that has an operator (). The importance of functors is that they can be used in many contexts in which C++ functions
can be used, whilst also having the ability to maintain state information. Next to
iterators, functors are one of the most fundamental ideas exploited by the STL.
The STL provides a number of pre-built functor classes; std::less, for example,
is often used to specify a default comparison function for algorithms that need to
determine which of two objects comes "before" the other.
#include <vector>
#include <algorithm>
#include <iostream>
512
5.2.5 Algorithms
The STL also provides several useful algorithms, in the form of template functions,
that are provided to, with the help of the iterator concept, manipulate the STL
containers (or derivations).
The STL algorithms arent restricted to STL containers, for instance:
#include <algorithm>
int array[10] = { 2,3,4,5,6,7,1,9,8,0 }
int* begin = &array[0];
int* end = &array[0] + 10;
std::sort( begin, end);// the sort algorithm will work on a C style array
513
Advanced Features
Non-modifying algorithms
Modifying algorithms
Removing algorithms
Mutating algorithms
Sorting algorithms
Sorted range algorithms
Numeric algorithms
Permutations
Sorting and related operations
sort
stable_sort
partial_sort
514
Smart Pointers
5.2.6 Allocators
Allocators are used by the Standard C++ Library (and particularly by the STL) to
allow parameterization of memory allocation strategies.
The subject of allocators is somewhat obscure, and can safely be ignored by most
application software developers. All standard library constructs that allow for specification of an allocator have a default allocator which is used if none is given by
the user.
Custom allocators can be useful if the memory use of a piece of code is unusual in
a way that leads to performance problems if used with the general-purpose default
allocator. There are also other cases in which the default allocator is inappropriate,
such as when using standard containers within an implementation of replacements
for global operators new and delete.
31
31
H T T P :// E N . W I K I B O O K S . O R G / W I K I /C A T E G O R Y %3AC%2B%2B%20P R O G R A M M I N G
515