Вы находитесь на странице: 1из 55

The Standard Template Library Tutorial

184.437 Wahlfachpraktikum (10.0


!ohanne" Weidl
Information Systems Institute
Distributed Systems Department
Technical University Vienna
Friday, 26. April 1996
Advisor Dipl. Ing. Georg Trausmuth
Professor DI Dr. ehdi !a"ayeri
"The Standard Template Library (STL) is a C++ programming library that
has been developed by Alexander Stepanov and Meng Lee at the Hewlett
a!"ard laboratories in alo Alto# Cali$ornia% &t was designed to enable a C+
+ programmer to do generi! programming and is based on the extensive 'se
o$ templates ( also !alled parametri)ed types% This paper tries to give a
!omprehensive and !omplete s'rvey on the STL programming paradigm and
shall serve as step(by(step t'torial $or the STL new!omer# who has
$'ndamental "nowledge in C++ and the ob*e!t(oriented paradigm%"
Table of contents
1 Introduction________________________________________________________________
2 C++ basics__________________________________________________________________
#.1 $la""e"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#.# &unction ob'ect"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#.3 Template"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#.$.% &unction templates'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
#.$.# (lass templates''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
#.$.$ Template member functions''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
#.$.) Template speciali"ation''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
3 A STL overview______________________________________________________________
3.1 STL a(ailability and information%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$.%.% &TP*Sites'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
$.%.# U+,s''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
3.# What doe" STL con"i"t of)%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3.3 $ompilin* STL pro*ram"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$.$.% -orland (.. )./ D0S*programs''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
$.$.# -orland (.. )./ 1I2D01S*programs''''''''''''''''''''''''''''''''''''''''''''''''''''
$.$.$ -orland (.. ).3 D0S* and 1I2D01S*programs''''''''''''''''''''''''''''''''''''''''''''
4 Learning STL_______________________________________________________________
4.1 $ontainer"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
).%.% Vector''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
).%.# 45ercises'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
4.# +terator"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
).#.% Input Iterators and 0utput Iterators''''''''''''''''''''''''''''''''''''''''''''''''''''''''
).#.# &or6ard Iterators''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
).#.$ -idirectional Iterators'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
).#.) +andom Access Iterators''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
).#.3 45ercises'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
4.3 ,l*orithm" and &unction -b'ect"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
).$.% 7o6 to create a generic algorithm'''''''''''''''''''''''''''''''''''''''''''''''''''''''''
).$.# The ST, algorithms''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
).$.$ 45ercises'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
4.4 ,daptor"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
).).% (ontainer Adaptors'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
).).# Iterator Adaptors'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
).).$ &unction Adaptors''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
4.. ,llocator" and memory handlin*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5 The remaining STL comonents________________________________________________
3.% 7o6 components 6or8 together''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
3.# Vector'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
3.$ ,ist'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
3.) De9ue'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
3.3 Iterator Tags''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
3.: Associative (ontainers''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
! Co"right__________________________________________________________________
# Literature__________________________________________________________________
STL Tutorial page 2 Johannes Weidl
1 Introduction
/oti(ation. In the late ;/s Ale5ander Stepanov first observed that some algorithms do not depend on
some particular implementation of a data structure but only on a fe6 fundamental semantic properties
of the structure. Such properties can be * for e5ample * the ability< to get from one element of the data
structure to the ne5t< and to be able to step through the elements from the beginning to the end of the
structure. &or a sort algorithm it is not essential if the elements to be sorted are stored in an array< a
lin8ed list< etc. Stepanov e5amined a number of algorithms and found that most of them could be
abstracted a6ay from a particular implementation and that this abstraction can be done in a 6ay that
efficiency is not lost. 4fficiency is an essential point that Stepanov emphasi"es on< he is convinced that
no one 6ould use an algorithm that becomes inefficient by instantiating it bac8.
The STL hi"tory. Stepanovs insight * 6hich hasn=t had much influence on soft6are development so far
* 6ill lead to a ne6 programming paradigm in future * so the hope of its discoverer. In %>?3 Stepanov
developed a generic Ada library and 6as as8ed< if he could do this in (.. as 6ell. -ut in %>?;
templates @see section #.$A * an essential techni9ue for this style of programming * 6eren=t implemented
in (.. and so his 6or8 6as delayed. In %>?? Stepanov moved to the 7P ,abs and %>># he 6as
appointed as manager of an algorithm proBect. 1ithin this proBect< Ale5ander Stepanov and eng ,ee
6rote a huge library * the Standard Template ,ibrary @ST,A * 6ith the intention to sho6 that one can
have algorithms defined as generically as possible 6ithout losing efficiency.
STL and the ,0S+1+S- $22 3raft Standard. The importance of ST, is not only founded in its
creation or e5istence< ST, 6as adopted into the draft standard at the !uly %)< %>>) A2SICIS0 (..
Standards (ommittee meeting. That means that if not happened till no6 any6ay< compiler vendors 6ill
soon be incorporating ST, into their products. The broad availability of ST, and the generic
programming idea give this ne6 programming paradigm the chance to positively influence soft6are
development * thus allo6 programmers to 6rite code faster and to 6rite less lines of code 6hile focusing
more on problem solution instead of 6riting lo6*level algorithms and data structures.
3ocument arran*ement. In section # ST,*re9uired (.. basics are taught< especially classes< function
obBect design and templates * also called parametri"ed types. In section $ ST, is overvie6ed and the 8ey
concepts are e5plained. Section ) teaches ST, step*by*step. Section 3 deals 6ith ST, components not
e5plained in section ). Section : contains copyright notices and section ; sho6s the literature used.
2 C++ basics
STL "pecific $22 ba"ic". This section gives a short survey on ST,*re9uired (.. basics< such as
classes< function obBects and templates. It tries to point out the ST,*specific aspects. &or a fundamental
and comprehensive study and understanding of these topics read D%E< F3 to F?.
2.1 Classes
4"er5defined type". 0ne reason to develop ( into (.. 6as to enable and encourage the programmer to
use the obBect*oriented paradigm. GThe aim of the (.. class concept D...E is to provide the programmer
6ith a tool for creating ne6 types that can be used as conveniently as the built*in typesG< says -Barne
Stroustrup< the father of (..< in D%E. It is stated that a class is a user*defined typeH
STL Tutorial page 3 Johannes Weidl
class shape {
private:
int x_pos;
int y_pos;
int color;
public:
shape () : x_pos(0), y_pos(0), color(1) {}
shape (int x, int y, int c = 1) : x_pos(x), y_pos(y), color(c) {}
shape (const shape& s) : x_pos(s.x_pos), y_pos(s.y_pos), color(s.color) {}
shape () {}
shape& operator= (const shape& s) {
x_pos = s.x_pos, y_pos = s.y_pos, color = s.color; return this; }
int !et_x_pos () { return x_pos; }
int !et_y_pos () { return y_pos; }
int !et_color () { return color; }

voi" set_x_pos (int x) { x_pos = x; }
voi" set_y_pos (int y) { y_pos = y; }
voi" set_color (int c) { color = c; }
virtual voi" #ra$%hape () {}
&rien" ostrea'& operator(( (ostrea'& os, const shape& s);
};
ostrea'& operator(( (ostrea'& os, const shape& s) {
os (( )shape: () (( s.x_pos (( ),) (( s.y_pos (( ),) (( s.color (( )));
return os;
}
67aminin* the $22 cla"" 8"hape8. The 8ey6ord class begins the definition of the user*defined type.
The 8ey6ord private means that the names x_pos, y_pos and color can only be used by member
functions @6hich are functions defined inside the class definitionA. The 8ey6ord public starts the
public*section< 6hich constitutes the interface to obBects of the class< that means< names and member
functions in this section can be accessed by the user of the obBect. -ecause of the attributes being
private< the class has public member functions to get and set the appropriate values. These member
functions belong to the interface.
2ote that a class is abstract< 6hereas the instantiation of a class leads to an obBect< 6hich can be used
and modifiedH
shape *y%hape (1+, 10, ,);
int color = *y%hape.!et_color();
shape -e$%hape = *y%hape;
6here shape is the class name and *y.lass is an obBect of the class shape.
shape () : x_pos(0), y_pos(0), color(1) {}
is the default constructor * the constructor 6ithout arguments. A constructor builds and initiali"es an
obBect< and there are more possible 8inds of constructorsH
shape (int x, int y, int c = 1) : x_pos(x), y_pos(y), color(c) {}
This is a constructor 6ith three arguments 6here the third one is a default argumentH
shape *y%hape (10, 10);
results inH x_pos == 10< y_pos == 10< color == 1.
STL Tutorial page 4 Johannes Weidl
shape (const shape& s) : x_pos(s.x_pos), y_pos(s.y_pos), color(s.color) {}
This is an important constructor< the so*called copy*constructor. It is called 6hen you 6rite code li8e
thisH
shape *y%hape;
shape -e$%hape (*y%hape);
After that< *y%hape and -e$%hape have the same attributes< the obBect -e$%hape is copied from the
obBect *y%hape using the copy constructor.
2ote the argument const shape& s. The I means Greference toG< 6hen a function call ta8es place< the
shape is not copied onto the stac8< but only a reference @pointerA to it. This is important< 6hen the obBect
given as argument is huge< because then copying 6ould be very inefficient.
shape () {}
is the destructor. It is called< 6hen an obBect is destroyed * for e5ample 6hen it goes out of scope. The
shape destructor has nothing to do< because inside the shape class no dynamically allocated memory is
used.
shape& operator= (const shape& s) {
x_pos = s.x_pos, y_pos = s.y_pos, color = s.color; return this; }
-perator o(erloadin*. In (.. it is possible to overload operators * that is to give them a ne6 meaning
or functionality. There is a set of operators 6hich can be defined as member functions inside a class.
Among these the assignment operator can be found< 6hich is used 6hen 6riting the follo6ing codeH
shape *y%hape, -e$%hape;
-e$%hape = *y%hape;
2ote that the operator= is called for the left obBect< i.e. -e$%hape< so there must be only one argument
in the declaration. This is true for all other (.. operators as 6ell.
1hen a member function is called< the system automatically adds the this*pointer to the argument list.
The this*pointer points to the obBect< for 6hich the member function is called. -y 6riting return
this< the concatenation of assignments gets possibleH
shape /l"%hape, *y%hape, -e$%hape;
-e$%hape = *y%hape = /l"%hape;
int !et_x_pos () { return x_pos; }
gives you the value of x_pos. An e5plicit interface function is necessary< because private mebers cannot
be accessed from outside the obBect.
virtual voi" #ra$%hape () {}
declarates a function 6ith no arguments that dra6s the shape. -ecause a shape is abstract and 6e have
no idea of 6hat it loo8s li8e precisely< thereJs no implementation for #ra$%hape. The 8ey6ord virtual
means that this member function can be over6ritten in a derived class @see D%E< F:A. &or e5ample< a
class "ot could be derived from shape. #ra$%hape then 6ould be over6ritten to dra6 the dot at the
position @x_pos<y_posA and 6ith the colour color.
STL Tutorial page Johannes Weidl
9ut5to operator. 2o6 consider the definition of the operator((H
ostrea'& operator(( (ostrea'& os, const shape& s) {
os (( )shape: () (( s.x_pos (( ),) (( s.y_pos (( ),) (( s.color (( )));
return os;
}
The usual 6ay in (.. to display information on the screen is to 6riteH
cout (( )0ello, 1orl"2);
1ith the upper code 6e overload the p't(to(operator @operator((A to be able to send shapes directly to
an output streamH
shape *y%hape (3, 4);
cout (( *y%hape;
sho6s on the output screenH shape+ (,#-#.)
&rien" ostrea'& operator(( (ostrea'& os, const shape& s);
&riend and inline. The 8ey6ord &rien" in front of a function declaration means that this function has
access to the private members of the class< 6here the declaration ta8es place. Kou can see that x_pos<
y_pos and color are used directly by operator((. It=s also possible to define a 6hole class as $riend
class.
2ote that all member functions of shape are defined inside the class declaration. If so< the member
functions are all GinlineG. &nline means< that 6herever the function is called< the compiler creates no
function call but inserts the code directly to decrease overhead.
To inline a member function defined outside the class the 8ey6ord inline must be usedH
inline int shape::!et_x_pos () { return x_pos; }
0ice $la""e". &or ST, it=s 6ise to create classes that meet the re9uirements of /i!e Classes. &or
e5ample< -orland (.. e5pects an obBect to be stored in a container to have an assignment operator
defined. Additionally< if a container holds its obBects in a particular order< a operator li8e the operator(
must be defined @the latter to fi5 a half*orderA.
A class T is called ni!e iff it supportsH
1. (opy constructor 5 (const 5&)
+. Assignment operator 5& operator= (const 5&)
6. 49uality operator int operator== (const 5&, const 5&)
,. Ine9uality operator int operator2= (const 5&, const t&)
such thatH
1. 5 a(b); assert (a == b);
+. a = b; assert (a == b);
6. a == a;
,. a == b i&& b == a
3. (a == b) && (b == c) i'plies (a == c)
7. a 2= b i&& 2 (a == b)
STL Tutorial page ! Johannes Weidl
A member function 5::s(...) is called e0'ality preserving iff
a == b i'plies a.s (...) == b.s (...)
A class is called 45tra*2ice iff
all of its member functions are e9uality preserving
The theory of 2ice (lasses origins from a Boint 6or8 bet6een 7P and Andre6 Loenig from the -ell
,abs.
2.2 "unction ob#ects
The function5call operator. A function obBect is an obBect that has the $'n!tion(!all operator
@operator() A defined @or overloadedA.
These function obBects are of crucial importance 6hen using ST,.
(onsider an e5ampleH
class less {
public:
less (int v) : val (v) {}
int operator () (int v) {
return v ( val;
}
private:
int val;
};
This function obBect must be created by specifying an integer valueH
less less_than_&ive (3);
The constructor is called and the value of the argument v is assigned to the private member val. 1hen
the function obBect is applied< the return value of the overloaded function call operator tells if the
argument passed to the function obBect is less than valH
cout (( )+ is less than 3: ) (( (less_than_&ive (+) 8 )yes) : )no));
0utputH 1 is less than ,+ yes
Kou should get familiar 6ith this 8ind of programming< because 6hen using ST, you often have to pass
such function obBects as arguments to algorithms and as template arguments 6hen instantiating
containers< respectively.
2.3 Te$plates
Static type checkin*. (.. is a language that supports static type chec8ing. Static type chec8ing helps
to catch many errors during compilation< because the programmer has to fi5 the type of a name used.
Any violation of the type model leads to an error message and cancels compilation. So< run*time errors
decrease.
STL Tutorial page % Johannes Weidl
2.3.1 "unction te$plates
(onsider the follo6ing functionH
voi" s$ap (int& a, int& b) {
int t'p = a;
a = b;
b = t'p;
}
S:appin* inte*er". This function let=s you s6ap the contents of t6o integer variables. -ut
6hen programming 9uite a big application< it is probable that you have to s6ap float< long or
char variables< or even shape variables * as defined in section #. So< an obvious thing to do
6ould be to copy the piece of code @cut*n*pasteMA and to replace all ints by shapes< 6ouldn=t
itN
A dra6bac8 of this solution is the number of similar code pieces< that have to be administered.
Additionally< 6hen you need a ne6 s6ap function< you must not forget to code it< other6ise
you get a compile*time error. And no6 imagine the overhead 6hen you decide to change the
return type from voi" to int to get information< if the s6ap 6as successful * the memory
could be too lo6 to create the local t'p variable< or the assignment operator @see shapeA could
not be defined. Kou 6ould have to change all 5 versions of s$ap * and go insane...
Template" or 9arametri;ed type". The solution to this dar8*dra6n scenario are templates<
template functions are functions that are parametri"ed by at least one type of their argumentsH
te'plate (class 59
voi" s$ap (5& a, 5& b) {
5 t'p = a;
a = b;
b = t'p;
}
2ote that the T is an arbitrary type*name< you could use U or anyType as 6ell. The
arguments are references to the obBects< so the obBects are not copied to the stac8 6hen the
function is called. 1hen you 6rite code li8e
int a = 6, b = 3;
shape *y%hape, :our%hape;
s$ap (a, b);
s$ap (*y%hape, :our%hape);
the compiler GinstantiatesG the needed versions of s$ap< that means< the appropriate code is
generated. There are different template instantiation techni9ues< for e5ample manual
instantiation< 6here the programmer himself tells the compiler< for 6ich types the template
should be instantiated.
&unction template e7ample". 0ther e5amples for function templates areH
te'plate (class 59
5& 'in (5& a, 5&b) { return a ( b 8 a : b; }
te'plate (class 59
voi" print_to_cout (char 's!, 5& ob;) {
cout (( 's! (( ): ) (( ob; (( en"l;
}
STL Tutorial page & Johannes Weidl
To use the last template function< obBects given as the second argument must have the
operator(( defined< other6ise you 6ill get a compile*time error.
2.3.2 Class te$plates
$la"" template" to build container". The motivation to create class templates is closely
related to the use of containers. G7o6ever< container classes have the interesting property that
the type of obBects they contain is of little interest to the definer of a container class< but of
crucial importance to the user of the particular container. Thus 6e 6ant to have the type of the
contained obBect be an argument to a container classH D...EG< D%E< F?. That means that a
container * e.g. a vector * should be able to contain obBects of any type. This is achieved by
class templates. The follo6ing e5ample comes from D%E< F%.).$H
te'plate (class 59
class vector {
5 v;
int s<;
public:
vector (int s) { v = ne$ 5 =s< = s>; }
vector () { "elete=> v; }
5& operator=> (int i) { return v=i>; }
int !et_si<e() { return s<; }
};
2ote that no error*chec8ing is done in this e5ample. Kou can instantiate different vector*
containers 6hich store obBects of different typesH
vector(int9 int_vector (10);
vector(char9 char_vector (10);
vector(shape9 shape_vector (10);
Ta8e a loo8 at the notation< the type*name is ve!tor2spe!i$i!3type4%
2.3.3 Te$plate $e$ber functions
-y no6 there=s no compiler I 8no6 6hich could handle template member functions. This 6ill
change in the very future< because template member functions are designated in the (..
standard.
2.3.4 Te$plate speciali'ation
$ope :ith "pecial type feature". If there is a good reason< 6hy a compiler*generated template
for a special type does not meet your re9uirements or 6ould be more efficient or convenient to
use 6hen implemented in another 6ay< you can give the compiler a special implementation for
this type * this special implementation is called template spe!iali)ation. &or e5ample< 6hen
you 8no6< that a shape*vector 6ill al6ays hold e5actly one obBect< you can speciali"e the
vector*template as follo6sH
STL Tutorial page ( Johannes Weidl
class vector(shape9 {
shape v;
public:
vector (shape& s) : v(s) { }
shape& operator=> (int i) { return v; }
int !et_si<e() { return 1; }
};
,et=s use itH
shape *y%hape;
vector(shape9 sin!le_shape_vector (*y%hape);
Template speciali"ations can also be provided for template functions @D%E< Fr.%).3A and
template operators.
STL Tutorial page 1) Johannes Weidl
3 * STL o+er+ie,
ST, is a component library. This means that it consists of components * clean and formally sound
concepts. Such components are for e5ample containers * that are obBects 6hich store obBects of an
arbitrary type * and algorithms. -ecause of the generic approach ST, algorithms are able to 6or8 on
user*built containers and user*built algorithms can 6or8 on ST, containers * if the user ta8es some
strict re9uirements for building his components into consideration. This techni9ue * to guarantee the
interoperability bet6een all built*in and user*built components * is referred to as Gthe orthogonal
decomposition of the component spaceG. The idea behind ST, can easily be sho6n by the follo6ing
considerationH
Imagine soft6are components as a three*dimensional space. 0ne dimension represents the data types
@int< double< char< ...A< the second dimension represents the containers @array< lin8ed*list< ...A and the third
dimension represents the algorithms @sort< merge< search< ...A.
Figure 1: Component space
1ith this scenario given< iOBO8 different versions of code have to be designed * a sort algorithm for an
array of int< the same sort algorithm for an array of double< a search algorithm for a lin8ed*list of
double and so on. -y using template functions that are parametri"ed by a data type< the i*a5es can be
dropped and only BO8 versions of code have to be designed< because there has to be only one lin8ed*list
implementation 6hich then can hold obBects of any data*type. The ne5t step is to ma8e the algorithms
6or8 on different containers * that means that a search algorithm should 6or8 on arrays as 6ell as on
lin8ed*lists< etc. Then< only B.8 versions of code have to be created.
ST, embodies the above concept and is thus e5pected to simplify soft6are development by decreasing
development times< simplifying debugging and maintenance and increasing the portability of code.
ST, consists of five main components. 1hen I list them here< don=t get confused by the names and their
short description< they are e5plained one by one in detail later.
AlgorithmH computational procedure that is able to 6or8 on different containers
(ontainerH obBect that is able to 8eep and administer obBects
IteratorH abstraction of the algorithm*access to containers so that an algorithm is able to 6or8
on different containers
&unction 0bBectH
a class that has the function*call operator @operator() A defined
AdaptorH encapsulates a component to provide another interface @e.g. ma8e a stac8 out of a listA
At this point I recommend to read D#E< chapters % to ).
3.1 STL a+ailabilit- and infor$ation
3.1.1 "T./Sites
STL Tutorial page 11 Johannes Weidl
int< double< char< ...
array< lin8ed*list< ... sort< merge< search< ...
i
' k
The 7e6lett Pac8ard ST, by Ale5ander Stepanov and eng ,ee can be found atH
ftpHCCbutler.hpl.hp.comCpubCstlCstl."ip for -orland (.. ).5
ftpHCCbutler.hpl.hp.comCpubCstlCsharfile.P for G((
There are many other interesting things there< too. An alternative site is
ftpHCCftp.cs.rpi.eduCstl
This document deals 6ith the 7P implementation of ST,< but there are others toH
0bBectSpace ST,QToolLitR
&S&CG2U libg.. #.:.#H
ftpHCCprep.ai.mit.eduCpubCgnuClibg..*#.:.#.tar.g"
-oth 6or8 6ith the G2U (.. compiler G(( #.:.$ that can be found atH
ftpHCCprep.ai.mit.eduCpubCgnuCgcc*#.:.$.tar.g"
4specially for the 6or8 6ith 0bBectSpace ST,QToolLitR you should patch your G(( #.:.$
6ith the template fi5 that can be found at
ftpHCCftp.cygnus.comCpubCg..Cgcc*#.:.$*template*fi5
any e5amples for the 0bBectSpace ST,QToolLitR can be found at
ftpHCCbutler.hpl.hp.comCpubCstlCe5amples.g" @also ."ipA
3.1.2 01Ls
David ussers ST,*pageH
httpHCC666.cs.rpi.eduCmusserCstl.html
umit=s ST, 2e6bie guideH
httpHCC666.5raylith.6isc.eduC8hanCsoft6areCstlCST,.ne6bie.html
!oseph K. ,aurino=s ST, pageH
httpHCC6eber.u.6ashington.eduCbyte6aveCbyte6ave'stl.html
STL Tutorial page 12 Johannes Weidl
3.2 What does STL consist of2
7ere comes a list of the files included in the 7P*ST, .PIP pac8age 6ith the 7AS7 e5tensionH
D0(.PS ST, Document D#E
D0(-A+.PS ST, Document D#E 6ith changebars from the previous version
IP.PS
&I,4S.DI& Differences to the files of the previous version
+4AD.4 Information file
+4AD4.0,D Information file of the previous version
A,G0.7 algorithm implementations
A,G0-AS4.7 au5iliary algorithms for A,G0.7
IT4+AT0+.7 iterator implementations and iterator adaptors
&U2(TI02.7 operators< functions obBects and function adaptors
T+44.7 implementation of a red*blac8 tree for associative containers
-00,.7 defines bool type
PAI+.7 defines pair type to hold t6o obBects
T+IP,4.7 defines triple type to hold three obBects
74AP.7 heap algorithms
STA(L.7 includes all container adaptors
7AS7.7 hash implementation
7AS7-AS4.7 hashbase implementation needed by hash
T4P-U&.(PP au5iliary buffer for get'temporary'bufferH should be complied and lin8ed if
get'temporary'buffer< stable'partition< inplace'merge or stable'sort are used
T4P-U&.7 get'temporary'buffer implementation
P+0!4(T2.7 select%st and ident implementation
+A2D0.(PP random number generator< should be compiled and lin8ed if random'shuffle is used
D4&A,,0(.7 default allocator to encapsulate memory model
-V4(T0+.7 bit vector @vector template speciali"ationA< se9uence container
D4SU4.7 double ended 9ueue< seu9ence container
,IST.7 list< se9uence container
AP.7 map< associative container
U,TIAP.7 multimap< associative container
S4T.7 set< associative container
U,TIS4T.7 multiset< associative container
V4(T0+.7 vector< se9uence container
3o"1Windo:" specific include filesH
<u*e memory modelH
7UGA,,0(.7< 7D4SU4.7< 7,IST.7< 7AP.7< 7U,TAP.7< 7U,TS4T.7< 7S4T.7< 7V4(T0+.7
&ar memory modelH
&A+A,,0(.7< &D4SU4.7< &,IST.7< &AP.7< &U,TAP.7< &U,TS4T.7< &S4T.7
Lar*e memory modelH
,2GA,,0(.7< ,-V4(T0+.7< ,D4SU4.7< ,,IST.7< ,AP.7< ,U,TAP.7< ,U,TS4T.7< ,S4T.7
0ear memory modelH
24+A,,0(.7< 2AP.7< 2U,TAP.7< 2U,TS4T.7< 2S4T.7
Table 1: STL include and documentation files
3.3 Co$piling STL progra$s
3.3.1 3orland C++ 4.) 45S/progra$s
STL Tutorial page 13 Johannes Weidl
$ommand Line.
Assume a (.. program named vector.cppH
?"e&ine __*@-*AB_#CD@-C# EE use %5FGs !eneric 'in an" 'ax te'plates
?"e&ine __H%C_%5F EE exclu"e I.JJGs re"un"ant operator "e&initions
EE %5F inclu"e &iles K inclu"e %5F &iles &irst2
?inclu"e )vector.h)
EE .JJ stan"ar" inclu"e &iles
?inclu"e (st"lib.h9 EE st"lib 'in an" 'ax &unctions are sLippe"
?inclu"e (cstrin!.h9 EE only co'pilable $ith __H%C_%5F "irective
?inclu"e (classlibMalloctr.h9 EE only co'pilable $ith __H%C_%5F "irective
?inclu"e (iostrea'.h9
voi" 'ain (voi")
{
vector(int9 v(3);
v=0> = ,;
cout (( )Dirst vector ele'ent: ) (( v=0>;
}
The compiler directive ?"e&ine __*@-*AB_#CD@-C# prevents the compilation of the 'in and
'ax functions in the -orland (.. include file (st"lib.h9< because ST, provides its o6n
template 'in and 'ax functions.
I recommend to include all ST, include files before the -orland (.. standard include files<
although this causes some 6or8 to be done.
There are some changes to be made in the include files (bc,Minclu"eMcstrin!.h9 and
(bc,Minclu"eMclasslibMalloctr.h9< if you plan to use them. Some operator definitions
have to be ta8en out of compilation< for e5ample by adding
?i& 2"e&ine" (__H%C_%5F) =...> ?en"i&,
because ST, generates these operators automatically using template operator definitions.
The code after adding the necessary ?i& directives @italic lettersA is sho6n in the follo6ing
bo5. The line numbers indicate the operator*definition*positions in the original include filesH
<bc4\include\cstring.h>:
line 724:
#if !defined(__USE_STL)
inline int _N5FC-5N: operator 2= ( const strin! _DAN &s1, const strin!
_DAN &s+ ) 50N/1_-/-C
{ =...> }
#endif
line 850:
#if !defined(__USE_STL)
inline int _N5FC-5N: operator (= ( const strin! _DAN &s1, const strin!
_DAN &s+ ) 50N/1_-/-C
{ =...> }
#endif
line 866:
#if !defined(__USE_STL)
inline int _N5FC-5N: operator 9 ( const strin! _DAN &s1, const strin!
_DAN &s+ ) 50N/1_-/-C
{ =...> }
#endif
STL Tutorial page 14 Johannes Weidl
line 882:
#if !defined(__USE_STL)
inline _N5FC-5N: operator 9= ( const strin! _DAN &s1, const strin! _DAN
&s+ )50N/1_-/-C
{ =...> }
#endif
<bc4\include\classlib\alloctr.h>, line 44:
#if !defined(__USE_STL)
&rien" voi" operator ne$( unsi!ne", voi" ptr )
{ return ptr; }
#endif
(ompile and lin8 .cpp files using ST, 6ith the follo6ing commandH
bcc K@(pathKtoKstlK"irectory9 (&ile9.cpp
45ampleH
bcc K@c:Mbc,Mstl vector.cpp
It is also possible to include the ST, include files after the -orland (.. standard include
files< then programs 6ould even compile 6ithout having changes in
(bc,Minclu"eMcstrin!.h9. -ut ST, provides a number of template functions that increase
genericity and template operator definitions that generate operator2= out of operator== and
operators 9< 9=< (= out of operator(< so it seems advisable to choose the practice sho6n
above.
+36 (+nte*rated 3e(elopment 6n(ironment.
(reate a proBect specifying GD0S*StandardG as target*platform. Specify the ST,*directory
under GoptionsCproBectCdirectoriesG @germanH G0ptionenCProBe8tCVer"eichnisseGA as include*
directory. Use the ?"e&ine __*@-*AB_#CD@-C# statement 6hen (st"lib.h9 is included< use
?"e&ine __H%C_%5F 6hen (cstrin!.h9 and (classlibMalloctr.h9 are included.
3.3.2 3orland C++ 4.) WI645WS/progra$s
As under D0S< the ?"e&ine __*@-*AB_#CD@-C# statement is needed 6hen (st"lib.hR is
included. Use ?"e&ine __H%C_%5F to compile your programs< 6hen using (cstrin!.h9 and
(classlibMalloctr.h9. Don=t forget to specify the ST,*directory as include*directory
under GoptionsCproBectCdirectoriesG @germanH G0ptionenCProBe8tCVer"eichnisseGA.
45ample programH
?"e&ine __*@-*AB_#CD@-C# EE use %5FGs !eneric 'in an" 'ax te'plates
?"e&ine __H%C_%5F EE exclu"e I.JJGs re"un"ant operator "e&initions
EE %5F inclu"e &iles
?inclu"e )vector.h)
?inclu"e )al!o.h)
EE .JJ stan"ar" inclu"e &iles
?inclu"e (st"lib.h9 EE st"lib 'in an" 'ax &unctions are sLippe"
?inclu"e (cstrin!.h9 EE only co'pilable $ith __H%C_%5F "irective
?inclu"e (classlibMalloctr.h9 EE only co'pilable $ith __H%C_%5F "irective
EE /1F+ inclu"e &iles
?inclu"e (o$lMo$lpch.h9
?inclu"e (o$lMapplicat.h9
STL Tutorial page 1 Johannes Weidl
int /$l*ain(int Ear!cE, char Ear!vE =>)
{
return 5Application().o'pile" $ith %5F inclu"e &iles)).Nun();
}
I encountered some problems 6hen compiling 6indo6s programs that ma8e e5tensive use of
ST, containers. The compiler comes up 6ith the error messages )co"e se!'ent excee"s
7,L) and )text se!'ent excee"s 7,L). The problem can be fi5ed by using the statements
?pra!'a co"ese! (co"ese!_na'e9 co"e and ?pra!'a co"ese! (textse!_na'e9
text< respectively.
3.3.3 3orland C++ 4. 45S/ and WI645WS/progra$s
&or programs 6ritten in -orland (.. ).3 all information given in sections $.$.% and $.$.# can
be applied but there are some further pointsH
The first include file has to be (classlibM"e&s.h9< because there -orland (.. defines
its bool type.
Then< all ST, include files have to be included @before any -orland (.. include filesA.
2ote< that the line numbers of operators that have to be commented out by a ?"e&ine
__H%C_%5F directive in the include files (cstrin!.h9 and (classlibMalloctr.h9 are
not the same as given in section $.$.% for the appropriate -orland (.. )./ include files.
A further operator has to be e5cluded by a ?"e&ine __H%C_%5F directive in the include
file (o$lMbitset.h9 @found at the end of the include fileA< if it is used.
D0S*e5ample @analogous for 1indo6sAH
?"e&ine __*@-*AB_#CD@-C# EE use %5FGs !eneric 'in an" 'ax te'plates
?"e&ine __H%C_%5F EE exclu"e I.JJGs re"un"ant operator "e&initions
?inclu"e (classlibM"e&s.h9 EE use I.JJ,.3 bool "e&inition
EE %5F inclu"e &iles
?inclu"e )vector.h)
EE .JJ stan"ar" inclu"e &iles
?inclu"e (st"lib.h9
?inclu"e (cstrin!.h9
?inclu"e (classlibMalloctr.h9
?inclu"e (o$lMbitset.h9
?inclu"e (iostrea'.h9
voi" 'ain (voi")
{
vector(int9 v(1, ,);
cout (( v=0>;
}
STL Tutorial page 1! Johannes Weidl
4 Learning STL
4.1 Containers
As -Barne Stroustrup says< G0ne of the most useful 8inds of classes is the container class< that is< a
class that holds obBects of some @otherA typeG< D%E< F?.%. (ontainers form one crucial component of ST,.
To sum up elements of a special type in a data structure< e.g. temperature values of an engine over a
definite distance of time< is a crucial tas8 6hen 6riting any 8ind of soft6are. (ontainers differ in the
6ay ho6 the elements are arranged and if they are sorted using some 8ind of 8ey.
In ST, you find Se0'en!e Containers and Asso!iative Containers. As described in D#E< GA se9uence is
a 8ind of container that organi"es a finite set of obBects< all of the same type< into a strictly linear
arrangementG. ST, provides three basic 8inds of Se9uence (ontainersH 5e!tors< Lists and 6e0'es<
6here De9ue is an abbreviation for 6o'ble 7nded 8'e'e.
Figure 2: Sequence Container
As Stepanov states< GAssociative containers provide an ability for fast retrieval of data based on 8eysG.
The elements are sorted and so fast binary search is possible for data retrieval. ST, provides four basic
8inds of Associative (ontainers. If the 8ey value must be uni9ue in the container< this means< if for each
8ey value only one element can be stored< Set and Map can be used. If more than one element are to be
stored using the same 8ey< M'ltiset and M'ltimap are provided.
Figure 3: Associative Container
7ere is a summary including all containers provided by ST,H
Se=uence $ontainer" >ector
3e=ue
Li"t
,""ociati(e $ontainer" Set
/ulti"et
/ap
/ultimap
Table 2: STL Containers
4.1.1 7ector
Assume 6e 6ant to develop a Graphical User Interface for a control station in an electric
po6er station. The single elements< li8e turbines< pipes and electrical installations are sho6n
STL Tutorial page 1% Johannes Weidl
Andy ary Peter Tom !ohn
!ohn Peter ary Andy Tom
on a screen. &or each po6er station element 6e derive a special class from the shape class in
section # to represent its loo8 on the screen. The class hierarchy could loo8 li8e thisH
Figure 4: !ample s"ape class "ierarc"#
1e store all shapes that are sho6n on a certain screen in the appropriate shape*container< e.g.
all turbine obBects that are sho6n on the main screen in a turbine*container. 1hen the screen is
called< the containers are used to dra6 a representation of the appropriate part of the po6er
station.
In (.. one could use an arrayH
turbine 'ain_screen_turbines ='ax_si<e>;
6here 'ax_si<e is the ma5imum number of turbine obBects that can be stored in the
'ain_screen_turbines array.
1hen you use ST,< you 6ould choose thisH
?inclu"e (vector.h9
typ"e& int turbine; EE so $e "onOt have to "e&ine the turbine class
int 'ain() {
vector(turbine9 'ain_screen_turbines;
return 0;
}
0ote? To ma8e this little e5ample run you have to read section $.$ on ho6 to compile ST,
programs. To use a vector in your program< include vector.h. In the follo6ing
e5amples only the essential code lines are presented and most of the include stuff and
the main function are omitted.
As you can see< you don=t have to specify a ma5imum si"e for the vector< because the vector
itself is able to dynamically e5pand its si"e. The ma5imum si"e the vector can reach * i.e. the
ma5imum number of elements it is able to store * is returned by the member function
'ax_si<e() of the vector classH
vector(turbine9::si<e_type 'ax_si<e = 'ain_screen_turbines.'ax_si<e();
0ote? any member functions described in the vector*section can be found among the rest of
the ST, containers< too. The description applies to those containers accordingly and
6ill be referenced 6hen discussing these containers.
STL Tutorial page 1& Johannes Weidl
shape
turbine horn pipe s6itch
electrical s6itch mechanical s6itch
si<e_type is an unsigned integral type< this could be for e5ample unsi!ne" lon!. The type
that determines the si"e of the different containers is encapsulated by a type"e& to abstract
from the actual memory model used. &or e5ampleH
type"e& unsi!ne" lon! si<e_type;
if the si"e is e5pressible by the built in type unsi!ne" lon!.
ST, abstracts from the specific memory model used by a concept named allo!ators. All the
information about the memory model is encapsulated in the Allocator class. 4ach container
is templati"ed @parametri"edA by such an allo!ator to let the implementation be unchanged
6hen s6itching memory models.
te'plate (class 5, te'plate (class H9 class Allocator = allocator9
class vector {
...
};
The second template argument is a default argument that uses the pre*defined allocator
GallocatorG< 6hen no other allocator is specified by the user. I 6ill describe allocators in
detail in section ).3.
If you 6ant to 8no6 the actual si"e of the vector * i.e. ho6 many elements it stores at the
moment * you have to use the si<e() member functionH
vector(turbine9 'ain_screen_turbines;
vector(turbine9::si<e_type si<e = 'ain_screen_turbines.si<e();
cout (( )actual vector si<e: ) (( si<e;
0utputH a!t'al ve!tor si)e+ 9
,i8e si<e_type describes the type used to e5press the si"e of a container< value_type gives
you the type of the obBects that can be stored in itH
vector(&loat9 v;
cout (( )value type: ) (( typei"
1
(vector(&loat9::value_type).na'e();
0utputH val'e type+ $loat
A container turns out useless if no obBect can be inserted into or deleted from it. The vector< of
course< provides member functions to do these Bobs and it does 9uite a bit moreH
It is g'aranteed that inserting and erasing at the end of the vector ta8es amorti)ed constant
time 6hereas inserting and erasing in the middle ta8es linear time.
As stated in D$E< +*3< GIn several cases< the most useful characteri"ation of an algorithm=s
computing time is neither 6orst case time nor average time< but amorti)ed time. D...E
Amorti"ed time can be a useful 6ay to describe the time ta8en by an operation on some
container in cases where the time !an vary widely as a se9uence of the operations is done< but
the total time for a se9uence of 2 operations has a better bo'nd than Bust 2 times the 6orst*
case time.G To understand this< remember that a vector is able to automatically e5pand its si"e.
This e5pansion is done< 6hen an insert command is issued but no room is left in the storage
allocated. In that case< ST, allocates room for #n elements @6here n is the actual si"e of the
containerA and copies the n e5isting elements into the ne6 storage. This allocation and the
copying process ta8e linear time. Then the ne6 element is inserted and for the ne5t n(.
insertions only constant time is needed. So you need 0@nA time for n insertions< averaged over
the n insert operations this results in 0@%A time for one insert operation. This more accurately
reflects the cost of inserting than using the 6orst*case time 0@nA for each insert operation.
%
To use typei" include typein&o.h
STL Tutorial page 1( Johannes Weidl
0f course amorti"ed constant time is about the same overhead as you have 6hen using (C(..
arrays but note that it is important to be about the same * and not more.
&or the authors of ST, comple5ity considerations are very important because they are
convinced that component programming and especially ST, 6ill only be accepted 6hen there
is no @seriousA loss of efficiency 6hen using it.
aybe there are users 6ho can afford to 6or8 inefficiently but 6ell designed * most can not.
The follo6ing table sho6s the insert and erase overheads of the containers vector< list and
"ePue. Thin8 of these overheads 6hen choosing a container for solving a specific tas8.
Table 3: $nsert and erase over"eads for vector% list and deque
-efore 6e loo8 at the insert functionality< there is another thing to consider. 1hen a vector is
constructed using the default constructor @the default constructor is used 6hen no argument is
given at the declarationA< no memory for elements is allocatedH
vector(int9 v;
1e can chec8 this using the member function capacity(), 6hich sho6s the number of
elements for 6hich memory has been allocatedH
vector(int9::si<e_type capacity = v.capacity();
cout (( )capacity: ) (( capacity;
0utputH !apa!ity+ 9
At the first glance this doesn=t ma8e any sense but it gets clear 6hen you consider< that the
vector class itself is able to allocate memory for the obBects inserted. In (.. you 6ould fill
your turbine array as follo6sH
turbine turb;
turbine 'ain_screen_turbines ='ax_si<e>;
'ain_screen_turbines=0> = turb;
In ST, you can use this synta5< tooH
STL Tutorial page 2) Johannes Weidl
Container insert$erase overhead
at the beginning in the midd%e at the end
Vector linear linear amorti"ed constant
,ist constant constant constant
De9ue amorti"ed constant linear amorti"ed constant
turbine turb;
vector(turbine9 'ain_screen_turbines (10); EE allocate 'e'ory &or 10
EE ele'ents
'ain_screen_turbines=0> = turb;
2o6< 6e don=t use the default constructor but specify a number that tells the vector for ho6
many elements memory should be allocated. Then 6e use the overloaded subscribe operator
@operator=> A to insert a turbine obBect into the vector.
0ote? If you use the subscribe operator 6ith an inde5< for 6hich no memory has been
allocated @this is true for all indices 6hen declaring a vector 6ithout specifying a vector
si"eA< the result 6ill be undefinedM
To avoid memory allocation stuff the vector provides different member functions to insert
elements into the vector. These insert functions do automatic memory allocation and * if
necessary * e5pansion. To append an element at the end of a vector use push_bacL()H
vector(int9 v;
v.push_bacL (6);
cout (( v.capacity() (( en"l;
cout (( v=0>;
0utputH 19:;
#
<
Three different @overloadedA 8inds of insert() member functions can be used. 7ere comes
the firstH
vector(int9 v;
v.insert (v.en"(), 6);
cout (( v.capacity() (( en"l;
cout (( v=0>;
0utputH 19:;
<
This first 8ind of the insert() member function needs t6o argumentsH an iterator GpointingG
to a definite container position and an element 6hich is to be inserted.
The element is inserted before the specified iterator(position< that is before the element the
specified iterator points to.
The term iterator needs some e5planation. There are t6o member functions 6hich return so*
called iteratorsH be!in() and en"().
Iterators are a generali"ation of the (.. pointers. An iterator is a 8ind of pointer but indeed
more than a pointer. ,i8e a pointer is dereferenced by the e5pression =pointer< an iterator has
the dereference operator defined 6hich returns a value of a specific type * the value type of
the iterator. Additionally< li8e a pointer can be incremented by using the operatorJJ< an
iterator can be incremented in the same 6ay. Iterators most often are associated 6ith a
container. In that case< the value type of the iterator is the value type of the container and
dereferencing the iterator returns an obBect of this value type. ,oo8 at this e5ample to get a
feeling ho6 iterators behaveH
#
This value depends on the environment @memory modelA used
STL Tutorial page 21 Johannes Weidl
vector(int9 v(6);
v=0> = 3;
v=1> = +;
v=+> = Q;
vector(int9::iterator &irst = v.be!in();
vector(int9::iterator last = v.en"();
$hile (&irst 2= last)
cout (( &irstJJ (( ) );
0utputH , 1 >
v.be!in() returns an iterator to the first element in the vector. The iterator can be
dereferenced and incremented li8e a (.. pointer.
Please note< that v.en"() doesn=t return an iterator that points to the last element in the vector
* as no6 could be supposed * but past the last element @ho6ever< in the ST, code such an
iterator is named lastA. Accordingly it is called past(the(end iterator. A user is not supposed
to dereference such an iterator< because the result 6ould be undefined. The $hile loop chec8s
if the &irst iterator is e9ual to the last iterator. If not< the iterator is dereferenced to get the
obBect it is pointing to< then it is incremented. So< all vector elements are 6ritten to cout.
Figure &: 'ange specified b# iterators
A range =i, ;) given by the iterators i and ; is valid< if ; is rea!hable from i< that means
if there is a finite se9uence of applications of operatorJJ to i that ma8es i==;T
+anges given by t6o iterators are very important in ST,< because ST, algorithms largely
6or8 in the follo6ing 6ayH
sort (be!inKiterator, past_the_en"Kiterator)
6here be!inKiterator specifies the first element in the range and past_the_en"Kiterator
points past the last element of the range to be sorted.
The range is correctly specified by the e5pression =be!inKiterator, past_the_en"K
iterator).
A valid sort command for our vector*e5ample 6ould beH
STL Tutorial page 22 Johannes Weidl
obBect of type
val'e3type
Andy !ohn Peter ary Tom
iterator returned by
member function
begin()
iterator returned by
member function
end()
range Dbegin@A< end@A A
sort
6
(v.be!in(), v.en"() );
Using iterators as intermediates< 6e are able to seperate the algorithms from the container
implementationsH
Figure (: )rt"ogonal decomposition of t"e component space
After this short survey on iterators< 6hich 6ill be described in very detail in the ne5t section<
6e focus on the vector container again.
1e learned that specifying a number 6hen declaring a vector reserves memory for elements.
Additionally to that< you can give the elements for 6hich memory is reserved an initial valueH
vector(int9 v(6, 1Q);
&or (int i = 0; i ( 6; iJJ) cout (( v=i> (( ) );
0utputH .> .> .>
It is possible to construct a vector out of another or to assign one vector to another vectorH
vector(&loat9 v (3, 6.+3);
vector(&loat9 v_ne$1 (v); EE construct v_ne$1 out o& v
vector(&loat9 v_ne$+ = v; EE assi!n v to vne$+
vector(&loat9 v_ne$6 (v.be!in(), v.en"() );
EE construct v_ne$6 out o& the ele'ents o& v
The last version uses iterators to specify the range out of 6hich the v_ne$6 vector should be
constructed. The three v_ne$ * vectors are all e9ualH
(v_ne$1 == v_ne$+) && (v_ne$+ == v_ne$6) && (v_ne$1 == v_ne$6) 8 M
cout (( )ePual) : cout (( )"i&&erent);
0utputH e0'al
To be able to compare vectors< an e9uality operator== for vectors is provided.
To s6ap t6o vectors< a special member function is provided 6hich needs merely constant
time< because only internal pointers are manipulated.
vector(int9 v (1, 10);
vector(int9 $ (1, +0);
v.s$ap ($);
cout (( v=0>;
$
To use algorithms in your programs you have to include al!o.h
STL Tutorial page 23 Johannes Weidl
$ontainer
,l*orithm
Iterator Iterator
0bBect
0utputH 19
1ith the member function e'pty() one can test if a vector is empty< i.e. if its si"e is "eroH
vector(char9 v;
v.e'pty() 8 cout (( )e'pty) : cout (( )not e'pty);
0utputH empty
The first and the last element are returned 6hen invo8ing &ront() and bacL()H
vector(int9 v (10, 3);
v.push_bacL (Q);
cout (( v.&ront() (( ) ) (( v.bacL();
0utputH , >
1ith pop_bacL() the last element is returned and deleted from the vector.
vector(int9 v (1, +);
int value = v.pop_bacL ();
cout (( value (( en"l;
v.e'pty() 8 cout (( )e'pty) : cout (( )not e'pty);
0utputH 1
empty
Additionally to the insert() member function that ta8es an iterator and an element as
arguments< t6o more versions are providedH
vector(int9 v;
v.insert (v.be!in(), +, 3); EE vector v: 3 3
vector(int9 $ (1, 6);
$.insert ($.en"(), v.be!in(), v.en"() ); EE vector $: 6 3 3
The second argument of the first version specifies ho6 many copies of an element * given as
third argument * should be inserted before the specified iterator*position @first argumentA. The
second version ta8es additionally to the inserting position $.en"() t6o iterators that specify
the range 6hich is to be inserted.
Using the erase() member function< it is possible to erase single elements or ranges
@specified by t6o iteratorsA from a vector. Accordingly< there are t6o versions of erase().
4rasing at the end of the vector ta8es constant time 6hereas erasing in the middle ta8es linear
time.
vector(&loat9 v (,, R.0); EE vector v: R.0 R.0 R.0 R.0
v.erase (v.be!in() ); EE vector v: R.0 R.0 R.0
v.erase (v.be!in(), v.en"() ); EE vector v:
The first version erases the first vector element. The second version erases all remaining
elements so the vector gets empty.
1hen inserting in or erasing from a container< there is something to ta8e into consideration. If
you have an iterator pointing e.g. to the end of a vector and you insert an element at its
beginning< the iterator to the end gets invalid. 0nly iterators before the insertion point remain
valid. If no place is left and e5pansion ta8es place< all iterators get invalid. This is clear<
because ne6 memory is allocated< the elements are copied and the old memory is freed.
STL Tutorial page 24 Johannes Weidl
Iterators aren=t automatically updated and get invalid< that means the result of operations
using such iterators is undefined. Ta8e this into consideration 6hen inserting or erasing and
then using iterators earlier defined on this container. The follo6ing table sho6s the validity of
the containers vector< list and "ePue after inserting and erasing an element< respectively.
Table 4: $terator validit# after inserting or erasing
2o6 6e are able to store obBects in a container @at least in the vectorA that provides several
means to administer and maintain it. To apply algorithms to the elements in the vector 6e have
to understand the iterator concept 6hich is described in detail in the ne5t section.
4.1.2 89ercises
This section contains specifications for e5ercises dealing 6ith the topics in section ).%.
Solving these tas8s should give you the possibility to apply your lections learned and compare
your solutions 6ith the ones given in the solutions part of this tutorial.
7xer!ise :%.%.+ 1rite a ST, program that declares a vector of integer values< stores five
arbitrary values in the vector and then prints the single vector elements to cout. -e sure
to have read section $.$ on ho6 to compile ST, programs.
7xer!ise :%.%1+ 1rite a ST, program that ta8es an arbitrary se9uence of binary digits @integer
values / and %A from cin and stores them into a container. 1hen receiving a value
different from 0 or 1 from cin stop reading. 2o6< you should have a container storing a
se9uence of 0=s and 1=s. After finishing the read*process< apply a Gbit*stuffingG algorithm
to the container. -it*stuffing is used to transmit data from a sender to a receiver. To avoid
bit se9uences in the data< 6hich 6ould erroneously be interpreted as the stop flag @hereH
/%%%%%%/A< it is necessary to ensure that si5 consecutive 1=s in the data are splitted by
inserting a 0 after each consecutive five 1=s. <int? (omple5ity considerations @inserting
in the middle of a vector ta8es linear timeMA and the fact< that inserting into a vector can
ma8e all iterators to elements invalid should ma8e you choose the ST, container list. A
list of integers is defined li8e a vector by list(int9 l; All operations e5plained in the
vector section are provided for the list< too. Get an iterator to the first list element. As
long as this iterator is different from the en"() iterator increment the iterator and
dereference it to get the appropriate binary value. 2ote that an element is al6ays inserted
before a specified iterator*position and that this insertion doesn=t affect all the other
iterators defined 6hen using a list.
7xer!ise :%.%<+ +efine 7xer!ise :%.%1 and print the original bit se9uence and the Gbit*stuffedG
bit se9uence to cout. Use the hint from 7xer!ise :%.%1 to form a loop for the output
procedure.
7xer!ise :%.%:+ +efine 7xer!ise :%.%< and print out the absolute and relative e5pansion of the
bit se9uence. The absolute e5pansion is the e5pasion measured in bits @e.g. the bit*stuffed
se9uence has increased by 3 bitsA< the relative e5pansion is the percentage of the
e5pansion @e.g. the relative e5pansion bet6een the Gne6G and GoldG se9uence is 3.%#UA.
STL Tutorial page 2 Johannes Weidl
Container oeration iterator va%idit"
vector inserting reallocation necessary * all iterators get invalid
no reallocation * all iterators before insert point remain valid
erasing all iterators after erasee point get invalid
list inserting all iterators remain valid
erasing only iterators to erased elements get invalid
de9ue inserting all iterators get invalid
erasing all iterators get invalid
7xer!ise :%.%,+ +efine 7xer!ise :%.%: and 6rite the inverse algorithm to the one in 7xer!ise
:%.%1 that the receiver has to perform to get the initial binary data representation. After
the bit*stuffing and bit*unstuffing compare your list 6ith the original one using the
e9uality operator==. If the lists are e9ual< you did a fine Bob. 0ote? It is advisable to
include a plausibility test in your unstuff algorithm. After a se9uence of five consecutive
ones there must be a "ero< other6ise something 6ent 6rong in the stuffing algorithm.
4.2 Iterators
GIterators are a generali"ation of pointers that allo6 a programmer to 6or8 6ith different data structures
@containersA in a uniform mannerG< D#E. &rom the short survey in section ).%.% 6e 8no6 that iterators are
obBects that have operator returning a value of a type called the val'e type of the iterator.
Since iterators are a generali"ation of pointers it is assumed that every template function that ta8es
iterators as arguments also 6or8s 6ith regular pointers.
There are five categories of iterators. Iterators differ in the operations defined on them. 4ach iterator is
designed to satis$y a 6ell*defined set of re9uirements. These re9uirements define 6hat operations can be
applied to the iterator. According to these re9uirements the iterators can be assigned to the five
categories. Iterator categories can be arranged from left to right to e5press that the iterator category on
the left satisfies the re9uirements of all the iterator categories on the right @and so could be called more
po6erfulA.
Figure *: $terator categories
STL Tutorial page 2! Johannes Weidl
?andom A!!ess
Iterators
@idire!tional
Iterators
Aorward
Iterators
&np't
Iterators
B'tp't
Iterators
means< iterator category on the left satisfies the re9uirements of all iterator categories
on the right
This arrangement means that a template function 6ich e5pects for e5ample a bidirectional iterator can
be provided 6ith a random access iterator< but never 6ith a for6ard iterator. Imagine an algorithm that
needs random access to fulfil his tas8< but is provided 6ith a method that only allo6s to pass through
the elements successively from one to the ne5t. It simply 6on=t 6or8.
Iterators that point past the last element of a range are called past(the(end iterators. Iterators for 6hich
the operator is defined are called dere$eren!eable. It is never assumed that past*the*end iterators are
dereferenceable. An iterator value @i.e. an iterator of a specific iterator typeA that isn=t associated 6ith a
container is called sing'lar @iteratorA value. Pointers can also be singular. After the declaration of an
uninitiali"ed pointer 6ith
int x;
x is assumed to be singular. Dereferenceable and past*the*end iterators are al6ays non(sing'lar.
All the categories of iterators have only those functions defined that are reali"eable for that category in
@amorti"edA constant time. This underlines the efficiency concern of the library.
-ecause random access in a lin8ed list doesn=t ta8e constant time @but linear timeA< random access
iterators cannot be used 6ith lists. 0nly inputCoutput iterators up to bidirectional iterators are valid for
the use 6ith the container list. The follo6ing table sho6s the iterators that can be used 6ith the
containers vector< list and "ePue @of course all iterators that satisfy the re9uirements of the listed
iterators can be used as 6ellAH
Container Iterator Categor"
vector random access iterators
list bidirectional iterators
de9ue random access iterators
Table &: +ost po,erful iterator categories t"at can be used ,it" vector% list and deque
Iterators of these categories are returned 6hen using the member functions be!in or en" or declaring an
iterator 6ith e.g. vector(int9::iterator i;
The iterator categories 6ill be e5plained starting 6ith the input iterators and output iterators.
4.2.1 Input Iterators and 5utput Iterators
An input iterator has the fe6est re9uirements. It has to be possible to declare an input iterator.
It also has to provide a constructor. The assignment operator has to be defined< too. T6o input
iterators have to be comparable for e9uality and ine9uality. operator has to be defined and
it must be possible to increment an input iterator.
Input Iterator +e9uirementsH
constructor
assignment operator
e9ualityCine9uality operator
dereference operator
preCpost increment operator
STL Tutorial page 2% Johannes Weidl
0utput iterators have to satisfy the follo6ing re9uirementsH
0utput Iterator +e9uirementsH
constructor
assignment operator
dereference operator
preCpost increment operator
These abstract re9uirements should get clear if you loo8 at special input and output iterators
provided by the library * the istream iterator and the ostream iterator.
GTo ma8e it possible for algorithmic templates to 6or8 directly 6ith inputCoutput streams<
appropriate iterator*li8e template classes are providedG< D#E. These template classes are named
istrea'_iterator and ostrea'_iterator. Assume 6e have a file filled 6ith /=s and %=s.
1e 6ant to read the values from a file and 6rite them to cout. In (.. one 6ould 6riteH
i&strea'
,
i&ile ()exa'ple_&ile));
int t'p;
$hile (i&ile 99 t'p) cout
3
(( t'p;
0utput @e5ampleAH ..9.9...9...9..
0ote? The /=s and %=s in the file have to be separated by whitespa!es @blan8< tab< ne6line<
formfeed or carriage returnA.
Using an istream and an ostream iterator in combination 6ith the algorithm copy enables us to
6rite the follo6ingH
i&strea' i&ile ()exa'ple_&ile));
copy (istrea'_iterator
7
(int, ptr"i&&_t9 (i&ile),
istrea'_iterator(int, ptr"i&&_t9 (),
ostrea'_iterator(int9 (cout) );
The output 6ill be the same as in the above (.. e5ample. copy is an algorithm that ta8es t6o
iterators to specify the range from 6hich elements are copied and a third iterator to specify the
destination 6here the elements should be copied to. The template function loo8s as follo6sH
te'plate (class @nput@terator, class /utput@terator9
/utput@terator copy (@nput@terator &irst, @nput@terator last,
/utput@terator result);
The template arguments have semantic meaning< they describe the iterator categories of that
iterators provided to the function at least have to be. The iterators specifying the input range
have to be at least input iterators< that means that it must be possible to increment and
dereference them to get the appropriate values. The iterator specifying the result position has
to be at least of the output iterator category. Since for6ard< bidirectional and random access
iterators satisfy the re9uirements of input and output iterators< they can be used instead 6ith
the same functionality.
Dereferencing an output iterator has to result in a lval'e< that means it has to be possible to
assign a value to the dereferenced output iterator @that is as you 8no6 an obBect of the value
)
To use i&strea' include &strea'.h
3
To use streams li8e cin and cout and operator((< operator99 for streams include iostrea'.h
:
To use istrea'_iteator or ostrea'_iterator include iterator.h
If you have to include al!o.h @as in this e5ampleA< iterator.h is already included by al!o.h
STL Tutorial page 2& Johannes Weidl
type of the iteratorA. &or output iterators< the only valid use of the operator is on the left
side of the assignment statementH
a is an output iterator, t is a value o& value type 5
a = t; vali"
t = a; invali"
&or output iterators< the three follo6ing conditions should holdH
Assignment through the same value of the iterator should happen only once.
ostrea'_iterator(int9 r (cout);
r = 0;
r = 1;
is not a valid code se9uence.
Any iterator value sould be assigned before it is incremented.
ostrea'_iterator(int9 r (cout);
rJJ;
rJJ;
is not a valid code se9uence.
Any value of an output iterator may have at most one active copy at any given time.
EE i an" ; are output iterators
EE a an" b are values $ritten to a iterator position
i = ;;
iJJ = a;
; = b;
is not a valid code se9uence.
&or both input and output iterators algorithms 6or8ing on them are assumed to be single pass
algorithms. Such algorithms are never assumed to attempt to pass the same iterator t6ice.
&or input iterators r and s< r==s does not imply JJr == JJsH
i&strea' i&ile ()exa'ple_&ile)) EE exa'ple_&ile: 0 1 + 6
istrea'_iterator(int, ptr"i&&_t9 r (i&ile);
istrea'_iterator(int, ptr"i&&_t9 s (i&ile);
(r==s) 8 cout (( )ePual) : cout (( )not ePual);
cout (( en"l;
JJr;
JJs;
cout (( r (( en"l;
cout (( s (( en"l;
(r==s) 8 cout (( )ePual) : cout (( )not ePual);
cout (( en"l;
0utputH e0'al
1
<
STL Tutorial page 2( Johannes Weidl
e9ual
0ote? &or t6o input iterators a and b< a == b implies a == b. &or istream iterators< this
condition doesnJt hold.
1hen incrementing an input iterator< a value is read from the input stream and stored
temporarily in the input iterator obBect. Dereferencing the input iterator returns the value
stored.
The constructor of the istream iterator ta8es an input stream as its argument from 6hich
values are read. To yield an end*of*stream iterator 6hich represents the end of file @C/DA of the
input stream< the default constructor has to be used. To successfully construct an istream
iterator< t6o template arguments have to be provided< too. The first argument specifies the
type of the elements read from the input stream< the second is ptr"i&&_t< that is the type of
the difference of t6o pointers in the actual memory model @see section ).3 * allocatorsA.
The constructor of the ostream iterator can ta8e one or t6o arguments. 7o6ever< the first
argument specifies the output stream to 6hich values are 6ritten. The alternative second
argument is a string 6hich is printed bet6een the 6ritten values. ostrea'_iterator ta8es a
template argument 6hich determines the type of the values 6ritten to the output stream.
It 6ill often be as8ed to copy elements from an input stream @e.g. a fileA directly into a
containerH
vector(int9 v;
i&strea' i&ile ()exa'ple_&ile));
copy (istrea'_iterator(int, ptr"i&&_t9 (i&ile),
istrea'_iterator(int, ptr"i&&_t9 (),
bacL_inserter(v) );
The function bacL_inserter returns a bacL_insert_iterator. This is a so*called iterator
adaptor @e5plained in detail in section ).)A and is a 8ind of past*the*end iterator to the
container. The container< for 6hich a bac8 insert iterator is to be created< has to be handed
over to bacL_inserter. 1hen a value is 6ritten to the bac8 insert iterator< it is appended to
the specified container as its last element. If< for e5ample< v.en"() is used instead of the bac8
insert iterator in the e5ample above< all the values inserted 6ill be 6ritten to the same vector
position @v.en"()A< because v.en"() isnJt incremented after 6riting to it. This increment is
internally done by the bac8 insert iterator by calling the container member function
push_bacL.
4.2.2 "or,ard Iterators
&or6ard iterators have to satisfy the follo6ing re9uirementsH
STL Tutorial page 3) Johannes Weidl
&or6ard Iterator +e9uirementsH
constructor
assignment operator
e9ualityCine9uality operator
dereference operator
preCpost increment operator
The difference to the input and output iterators is that for t6o for6ard iterators r and s< r==s
implies JJr==JJs. A difference to the output iterators is that operator is also valid on the
left side of the assignment operator @t = a is validA and that the number of assignments to a
for6ard iterator is not restricted.
So< m'lti(pass one(dire!tional algorithms can be implemented on containers that allo6 the
use of for6ard iterators @loo8 at Table ,A. As an e5ample for a single*pass one*directional
algorithm &in"_linear is presented. It iterates through the elements of a container and
returns the iterator position 6here a value provided to &in"_linear is found< other6ise the
past*the*end iterator is returned. The overhead of &in"_linear is statistically nC1.
te'plate(class Dor$ar"@terator, class 59
Dor$ar"@terator &in"_linear (Dor$ar"@terator &irst,
Dor$ar"@terator last, 5& value) {
$hile (&irst 2= last) i& (&irstJJ == value) return &irst;
return last;
}
vector(int9 v (6, 1);
v.push_bacL (Q); EE vector v: 1 1 1 Q
vector(int9::iterator i = &in"_linear (v.be!in(), v.en"(), Q);
i& (i 2= v.en"() ) cout (( i; else cout (( )not &oun");
0utputH >
4.2.3 3idirectional Iterators
In addition to for6ard iterators< bidirectional iterators satisfy the follo6ing re9uirementsH
-idirectional Iterator +e9uirements @additional to for6ard iterators=AH
preCpost decrement operator
-idirectional iterators allo6 algorithms to pass through the elements for6ard and bac86ard.
list(int9 l (1, 1);
l.push_bacL (+); EE list l: 1 +
list(int9::iterator &irst = l.be!in();
list(int9::iterator last = l.en"();
$hile (last 2= &irst) {
KKlast;
cout (( last (( ) );
}
0utputH 1 .
STL Tutorial page 31 Johannes Weidl
The bubble sort algorithm serves as an e5ample for a multi*pass algorithm using bidirectional
iterators.
te'plate (class Ii"irectional@terator, class .o'pare9
voi" bubble_sort (Ii"irectional@terator &irst, Ii"irectional@terator last,
.o'pare co'p)
{
Ii"irectional@terator le&t_el = &irst, ri!ht_el = &irst;
ri!ht_elJJ;
$hile (&irst 2= last)
{
$hile (ri!ht_el 2= last) {
i& (co'p(ri!ht_el, le&t_el)) iter_s$ap (le&t_el, ri!ht_el);
ri!ht_elJJ;
le&t_elJJ;
}
lastKK;
le&t_el = &irst, ri!ht_el = &irst;
ri!ht_elJJ;
}
}
The binary function obBect .o'pare has to be provided by the user of bubble_sort.
.o'pare< 6hich implements a binary predicate< ta8es t6o arguments and returns the result
@true or &alseA of the predicate provided 6ith the t6o arguments.
list(int9 l;
EE &ill list
bubble_sort (l.be!in(), l.en"(), less(int9() ); EE sort ascen"in!ly
bubble_sort (l.be!in(), l.en"(), !reater(int9() );EE sort "escen"in!ly
4.2.4 1ando$ *ccess Iterators
In addition to bidirectional iterators< random access iterators satisfy the follo6ing
re9uirementsH
+andom Access Iterator +e9uirements @additional to bidirectional iterators=AH
operator. @intA
operator.V @intA
operator* @intA
operator*V @intA
operator* @random access iteratorA
operatorDE @intA
operator Q @random access iteratorA
operator R @random access iteratorA
operator RV @random access iteratorA
operator QV @random access iteratorA
+andom access iterators allo6 algorithms to have random access to elements stored in a
container 6hich has to provide random access iterators< li8e the vector.
STL Tutorial page 32 Johannes Weidl
vector(int9 v (1, 1);
v.push_bacL (+); v.push_bacL (6); v.push_bacL (,); EE vector v: 1 + 6 ,
vector(int9::iterator i = v.be!in();
vector(int9::iterator ; = i J +; cout (( ; (( ) );
i J= 6; cout (( i (( ) );
; = i K 1; cout (( ; (( ) );
; K= +;
cout (( ; (( ) );
cout (( v=1> (( en"l;
(; ( i) 8 cout (( ); ( i) : cout (( )not (; ( i)); cout (( en"l;
(; 9 i) 8 cout (( ); 9 i) : cout (( )not (; 9 i)); cout (( en"l;
i = ;;
i (= ; && ; (= i 8 cout (( )i an" ; ePual) : cout (( )i an" ; not ePual);
cout (( en"l;
; = v.be!in();
i = v.en"();
cout (( )iterator "istance en" K be!in =S si<e: ) (( (i K ;);
0utputH < : < . 1
* 2 i
not (i 4 *)
i and * e0'al
iterator distan!e end ( begin DE si)e+ :
An algorithm that needs random access to container elements to 6or8 6ith 0@ld nA is the
binary search algorithm. In section ).$ algorithms and function obBects are e5plained and it is
sho6n ho6 they 6or8 together in a very advantageous 6ay.
4.2. 89ercises
7xer!ise :%1%.+ +efine 7xer!ise :%.%, by reading the original bit se9uence out of a user built
file bit3se0. Additionally< store the bit*stuffed bit se9uence in the file bit3st$$ @note that
the integer values in the input and output stream have to be separated by 6hitespacesA.
<int? The output file bit3st$$ has to be declared as o&strea'< 6hich is defined li8e
i&strea' in &strea'.h.
4.3 *lgorith$s and "unction 5b#ects
All the algorithms provided by the library are parametri"ed by iterator types and are so seperated from
particular implementations of data structures. -ecause of that they are called generi! algorithms.
4.3.1 :o, to create a generic algorith$
I 6ant to evolve a generic binary sear!h algorithm out of a conventional one. The starting
point is a (.. binary search algorithm 6hich ta8es an integer array< the number of elements
in the array and the value searched for as arguments. binary_search returns a constant
pointer to the element * if found * the nil pointer else.
STL Tutorial page 33 Johannes Weidl
const int binary_search (const int array, int n, int x) {
const int lo = array, hi = array J n, 'i";
$hile(lo 2= hi) {
'i" = lo J (hi K lo) E +;
i& (x == 'i") return 'i";
i& (x ( 'i") hi = 'i"; else lo = 'i" J 1;
}
return 0;
}
,et us loo8 at the assumptions this algorithm ma8es about its environment. binary_search
only 6or8s 6ith integer arrays. To ma8e it 6or8 6ith arrays of arbitrary types 6e transform
binary_search in a template function.
te'plate(class 59
const 5 binary_search (const 5 array, int n, const 5& x) {
const 5 lo = array, hi = array J n, 'i";
$hile(lo 2= hi) {
'i" = lo J (hi K lo) E +;
i& (x == 'i") return 'i";
i& (x ( 'i") hi = 'i"; else lo = 'i" J 1;
}
return 0;
}
2o6 the algorithm is designed for use 6ith arrays of different types. In case of not finding the
value searched for< a special pointer * nil * is returned. This re9uires that such a value e5ists.
Since 6e don=t 6ant to ma8e this assumption< in case of an unsuccessful search 6e return the
pointer array J n @yes< a past*the*end pointerA instead.
te'plate(class 59
const 5 binary_search (const 5 array, int n, const 5& x) {
const 5 lo = array, hi = array J n, 'i";
$hile(lo 2= hi) {
'i" = lo J (hi K lo) E +;
i& (x == 'i") return 'i";
i& (x ( 'i") hi = 'i"; else lo = 'i" J 1;
}
return array J n;
}
Instead of handing over array as pointer to the first element and a si"e< 6e could also specify
a pointer to the first and past the last element to approach ST,=s iterator concept.
te'plate(class 59
const 5 binary_search (5 &irst, 5 last, const 5& value) {
const 5 lo = array, hi = array J n, 'i";
$hile(lo 2= hi) {
'i" = lo J (hi K lo) E +;
i& (value == 'i") return 'i";
i& (value ( 'i") hi = 'i"; else lo = 'i" J 1;
}
return last;
}
To specify a pointer to the end of a container instead of handing over its si"e has the
advantage that it has not to be possible to compute last out of &irst 6ith &irstJn. This is
important for containers that don=t allo6 random access to their elements. -ecause our
STL Tutorial page 34 Johannes Weidl
binary_search needs random access to the elements of the container< this is of little
importance in our e5ample. Another advantage is that the di$$eren!e type @here intA doesn=t
have to be e5plicitly handed over< so the user of binary_search doesn=t even have to 8no6 it.
The difference type is the type 6hich is used to e5press the type of the difference of t6o
arbitrary iterators @pointersA< for e5ample last * &irst could be of the type si!ne" lon!.
The last step to fully adapt the algorithm to the ST, style is to change the first and last pointer
type from pointers to the value type to an appropriate iterator type. -y this step< the
information of ho6 the algorithm steps from one element to the ne5t is torn a6ay from the
algorithm implementation and is hidden in the iterator obBects. 2o6< no assumptions about the
mechanism to iterate through the elements are made. This mechanism is handed over to the
algorithm by the iterator obBects. So< the algorithm is separated from the container it 6or8s
on< all the operations that deal 6ith iterators are provided by the iterator obBects themselves.
Since binary_search needs random access to the elements of the container it is called for
and so iterators handed over to binary_search have to satisfy the re9uirements of random
access iterators< 6e name the type of &irst and last GNan"o'Access@teratorGH
te'plate(class Nan"o'Access@terator, class 59
Nan"o'Access@terator binary_search (Nan"o'Access@terator &irst,
Nan"o'Access@terator last,
const 5& value) {
Nan"o'Access@terator not_&oun" = last, 'i";
$hile(&irst 2= last) {
'i" = &irst J (last K &irst) E +;
i& (value == 'i") return 'i";
i& (value ( 'i") last = 'i"; else &irst = 'i" J 1;
}
return not_&oun";
}
The only assumptions the algorithm ma8es are the random access to elements of type 5
bet6een the t6o iterators @pointersA &irst and last and that operator== and operator(
are defined for type 5 and the value type of the iterator.
This generic binary search algorithm hasn=t lost anything of its functionality< especially not
6hen dealing 6ith built in types.
int x=10>; EE array o& ten inte!er values
int search_value; EE value searche" &or
EE initiali<e variables
int i = binary_search (&x=0>, &x=10>, search_value);
i& (i == &x=10>) cout (( )value not &oun"); else cout (( )value &oun");
All the ST, algorithms are constructed li8e our e5ample algorithm * they try to ma8e as fe6
assumptions as possible about the environment they are run in.
STL Tutorial page 3 Johannes Weidl
4.3.2 The STL algorith$s
The algorithms delivered 6ith the library are divided into four groupsH
grou a%gorithm t"e
% mutating se9uence operations
# non*mutating se9uence operations
$ sorting and related operations
) generali"ed numeric operations
Table (: STL algorit"m t#pes
Group % contains algorithms 6hich don=t change @mutateA the order of the elements in a
container< this has not to be true for algorithms of group #.
The algorithm &or_each of group % ta8es t6o iterators and a function & of type Dunction as
argumentsH
te'plate (class @nput@terator, class Dunction9
Dunction &or_each (@nput@terator &irst, @nput@terator last, Dunction &);
The template argument & of type Dunction must not be mi5ed up 6ith a GpureG (.. function<
because such a function can only be used in a roundabout 6ay @see section ).).$A. The
template function &or_each e5pects a $'n!tion ob*e!t @section #.#A as argument. & is assumed
not to apply any non*constant function through the dereferenced iterator.
&or_each applies f to the result of dereferencing every iterator in the range =&irst, last)
and returns &. If & returns a value< it is ignored. The follo6ing e5ample computes the sum of
all elements in the range =&irst, last).
te'plate (class 59
class su'_up {
public:
voi" operator() (const 5& value) { su' J= value; }
const 5& rea"_su'() { return su'; }
private:
static 5 su';
};
int su'_up(int9::su';
voi" 'ain(voi") {
"ePue
Q
(int9 " (6,+);
su'_up(int9 s;
&or_each (".be!in(), ".en"(), s);
cout (( s.rea"_su'();
}
0utputH F
Group % also contains an algorithm &in"< 6hich is very similar to &in"_linear from section
).#.#.
;
To use a "ePue include "ePue.h
STL Tutorial page 3! Johannes Weidl
te'plate (class @nput@terator, class 59
@nput@terator &in"(@nput@terator &irst, @nput@terator last,
const 5& value);
&in" ta8es a range and a reference to a value of arbitrary type. It assumes that operator==
for the value type of the iterator and 5 is defined. Additionally to &in" an algorithm named
&in"_i& is provided< 6hich ta8es a predicate pre" of type Tre"icate.
te'plate (class @nput@terator, class Tre"icate9
@nput@terator &in"_i&(@nput@terator &irst, @nput@terator last,
Tre"icate pre");
&in"_i& @li8e &in"A returns the first iterator i in the range =&irst, last)< for 6hich the
follo6ing condition holdsH pre"(i) = true. If such an iterator doesn=t e5ist< a past*the end
iterator is returned.
te'plate (class 59
class &in"_&irst_!reater {
public:
&in"_&irst_!reater() : x(0) {}
&in"_&irst_!reater(const& xx) : x(xx) {}
int operator() (const 5& v) { return v 9 x; }
private:
5 x;
};
vector(int9 v;
EE &ill vector $ith 1 + 6 , 3
vector(int9::iterator i = &in"_i& (v.be!in(), v.en"(),
&in"_&irst_!reater(int9 (6));
i 2= v.en"()8 cout (( i : cout (( )not &oun");
0utputH :
Generally< if there is a version of an algorithm 6hich ta8es a predicate< it gets the name of the
algorithm 6ith the suffi5 _i&.
Some algorithms< li8e a";acent_&in"< ta8e a binary predicate binary_pre" of type
IinaryTre"icate. a";acent_&in" returns the first iterator i< for 6hich the follo6ing
condition holdsH binary_pre" (i, (iJ1)) == true.
te'plate (class @nput@terator, class IinaryTre"icate9
@nput@terator a";acent_&in"(@nput@terator &irst, @nput@terator last,
IinaryTre"icate binary_pre");
&or e5ample< if you 6ant to find the first pair of values< 6hose product is odd< you could
6rite thisH
te'plate (class 59
class pro"_o"" {
public:
int operator() (const 5& v1, const 5& v+)
{ return v1U+ 2= 0 && v+U+ 2= 0; }
};
list(int9 l;
EE &ill list $ith + 4 7 16 Q
list(int9::iterator i = a";acent_&in" (l.be!in(), l.en"(),
pro"_o""(int9());
i& (i 2= l.en"()) { cout (( i (( ) ); iJJ; cout (( iJJ; }
else cout (( )not &oun");
STL Tutorial page 3% Johannes Weidl
0utputH .< >
Algorithms can 6or8 in pla!e< that means they do their 6or8 6ithin the specified range.
Some algorithms have an additional version 6hich copies 6ell*defined elements to an output
iterator result. 1hen such a version is provided< the algorithm gets the suffi5 _copy @6hich
precedes a probable suffi5 _i&A. &or e5ample there is replace_copy_i&< 6hich assigns to
every iterator in the range =result, resultJ(lastK&irst) ) either a ne6 value @6hich
has to be specifiedA or the original value. This depends on a predicate given as argument.
te'plate (class @terator, class /utput@terator, class Tre"icate, class 59
/utput@terator replace_copy_i&(@terator &irst, @terator last,
/utput@terator result, Tre"icate pre",
const 5& ne$_value);
All the operations in group $ have t6o versions. 0ne that ta8es a function obBect co'p of type
.o'pare and another that uses operator( to do the comparison. operator( and co'p<
respectively< have to induce a total ordering relation on the values to ensure that the algorithms
6or8 correctly.
vector(int9 v;
EE &ill v $ith 6 Q 3 , + 7
sort (v.be!in(), v.en"() );
sort (v.be!in(), v.en"(), less(int9() );
sort (v.be!in(), v.en"(), !reater(int9() );
0utputH 1 < : , F >
1 < : , F >
> F , : < 1
Since the library provides function obBects for all of the comparison operators in the language
6e can use less to sort the container ascendingly and !reater to sort it descendingly.
All the provided function obBects are derived either from unary_&unction or from
binary_&unction to simplify the type definitions of the argument and result types.
te'plate (class Ar!, class Nesult9
struct unary_&unction {
type"e& Ar! ar!u'ent_type;
type"e& Nesult result_type;
};
te'plate (class Ar!1, class Ar!+, class Nesult9
struct binary_&unction {
type"e& Ar!1 &irst_ar!u'ent_type;
type"e& Ar!+ secon"_ar!u'ent_type;
type"e& Nesult result_type;
};
ST, provides function obBects for all of the arithmetic operations in the language. plus<
'inus< ti'es< "ivi"es and 'o"ulus are binary operations 6hereas ne!ate is a unary
operation. As e5amples< loo8 at plus and ne!ate< the other functions obBects are defined
accordingly.
te'plate (class 59
struct plus : binary_&unction(5, 5, 59 {
5 operator()(const 5& x, const 5& y) const { return x J y; }
};
te'plate (class 59
struct ne!ate : unary_&unction(5, 59 {
STL Tutorial page 3& Johannes Weidl
5 operator()(const 5& x) const { return Kx; }
};
The mentioned comparison function obBects are ePual_to< not_ePual_to< !reater< less<
!reater_ePual and less_ePual< they are all binary function obBects. less shall serve as
e5ample.
te'plate (class 59
struct less : binary_&unction(5, 5, bool9 {
bool operator()(const 5& x, const 5& y) const { return x ( y; }
};
Additionally< the binary function obBects lo!ical_an" and lo!ical_or e5ist< lo!ical_not
is a unary function obBect.
te'plate (class 59
struct lo!ical_an" : binary_&unction(5, 5, bool9 {
bool operator()(const 5& x, const 5& y) const { return x && y; }
};
te'plate (class 59
struct lo!ical_not : unary_&unction(5, bool9 {
bool operator()(const 5& x) const { return 2x; }
};
The rest of the function obBect implementations can be found in D#E< :.
In group )< the algorithm accu'ulate ta8es a binary operation binary_op of type
Iinary/peration. The algorithm accu'ulate does the same as &or_each used 6ith the
function obBect su'_up @presented earlier in this sectionA.
te'plate (class @nput@terator, class 59
5 accu'ulate(@nput@terator &irst, @nput@terator last, 5 init);
&or each iterator i in =&irst, last)< acc = acc J i is computed< then acc is returned.
acc can be initiali"ed 6ith a starting value. Instead of operatorJ< an arbitrary binary
operation can be defined by the user< or a ST, function obBect can be used.
vector(int9 v;
v.push_bacL (+); v.push_bacL (3);
cout (( accu'ulate (v.be!in(), v.en"(), 10, "ivi"es(int9() );
0utputH .
I 6ant to present an e5ample 6hich implements a spell*chec8er. &or this purpose 6e assume
the follo6ingH
The dictionary is stored in a file
The te5t to chec8 is stored in a file
The 6ords of the te5t should be chec8ed against dictionary
4very 6ord not found or misspelled should be displayed
1e decide to use a non*associative container @see section ).%< introductionA< 6hich holds the
dictionary. The dictionary is assumed to be sorted. 2o6< 6e e5press the spell*chec8er
functionality in pseudo code.
&or every $or" in text
checL a!ainst "ictionary
i& not in "ictionary $rite to output
STL Tutorial page 3( Johannes Weidl
This pseudo code can be e5pressed in different 6ayH
copy every $or" o& text to output
that is not in the "ictionary
The last pseudo code variation can more directly be translated into a ST, program. Since 6e
need a mechanism that tells us if a 6ord is or is not in the dictionary< 6e encapsulate this
functionality in a function obBect.
te'plate (class bi"irectional_iterator, class 59
class nonAssocDin"er {
public:
nonAssocDin"er(bi"irectional_iterator be!in,
bi"irectional_iterator en") :
_be!in(be!in), _en"(en") {}
bool operator() (const 5& $or") {
return binary_search(_be!in, _en", $or"); }
private:
bi"irectional_iterator _be!in;
bi"irectional_iterator _en";
};
The function obBect nonAssocDin"er is initiali"ed 6ith the iterators be!in and en" that have
to be at least of the bidirectional iterator category. The function call operator ta8es a 6ord and
returns a boolean value< 6hich states if the 6ord has been found in the dictionary @the type
bool is defined by ST,A. This boolean value is returned by the ST, algorithm
binary_search.
te'plate (class Dor$ar"@terator, class 59
bool binary_search(Dor$ar"@terator &irst, Dor$ar"@terator last,
const 5& value);
The first thing 6e do in our program is to define a dictionary as a vector of type strin! and
fill it out of an input stream.
type"e& vector(strin!
R
9 "ict_type;
i&strea' "ictDile()"ict.txt));
i&strea' $or"sDile()$or"s.txt));
"ict_type "ictionary;
copy (istrea'_iterator(strin!, ptr"i&&_t9("ictDile),
istrea'_iterator(strin!, ptr"i&&_t9(),
bacL_inserter("ictionary));
?
To use the strin! type include cstrin!.h
STL Tutorial page 4) Johannes Weidl
Then 6e use the ST, algorithm re'ove_copy_i& to achieve the functionality 6anted.
te'plate (class @nput@terator, class /utput@terator, class Tre"icate9
/utput@terator re'ove_copy_i&(@nput@terator &irst, @nput@terator last,
/utput@terator result, Tre"icate pre");
re'ove_copy_i& 6rites all elements referred to by the iterator i in the range =&irst, last)
to the output iterator result< for 6hich the follo6ing condition does not holdH
pre"(i) == true. The algorithm returns the end of the resulting range. The rest of the
spell*chec8er program proves to be a single statement.
re'ove_copy_i& (
istrea'_iterator(strin!, ptr"i&&_t9($or"sDile),
istrea'_iterator(strin!, ptr"i&&_t9(),
ostrea'_iterator(strin!9(cout, )Mn)),
nonAssocDin"er("ict_type::iterator,
"ict_type::value_type9
("ictionary.be!in(), "ictionary.en"()));
re'ove_copy_i& reads 6ords from the input stream $or"sDile and 6rites the 6ords for
6hich nonAssocDin"er returns &alse @i.e. 6hich are either not found or misspelledA to cout.
The components used areH
algorithmsH copy and re'ove_copy_i&
containerH vector
user definedH function obBect nonAssocDin"er
2o6 you should have the basics to understand the chapter on algorithms in D#E< %/. Since this
document is very theoretical< the algorithms in combination 6ith a description and e5amples
can be found in D)E< :. A complete ST, e5ample can be found in D)E< 3.
4.3.3 89ercises
7xer!ise :%<%.+ &ill t6o containers 6ith the same number of integer values. (reate a ne6
container< 6hose elements are the sum of the appropriate elements in the original
container. <int? The library provides an algorithm and a function obBect to do the
e5ercise.
7xer!ise :%<%1+ 1rite a generator obBect 6hich can be used 6ith the ST, algorithm !enerate
@group #A to fill containers 6ith certain values. It should be possible to specify a starting
value and a step si"e< so that the first element in the container is the starting value and
every further element is the sum of the preceding element and the step si"e.
4.4 *daptors
As stated in D#E< %%< GAdaptors are template classes that provide interface mappingsG. Adaptors are
classes that are based on other classes to implement a ne6 functionality. ember functions can be
added or hidden or can be combined to achieve ne6 functionality.
STL Tutorial page 41 Johannes Weidl
4.4.1 Container *daptors
Stack. A stac8 can be instantiated either 6ith a vector< a list or a "ePue. The member
functions e'pty< si<e< top< push and pop are accessible to the user.
stacL
4
(vector(int9 9 s1;
stacL(list(int9 9 s+;
stacL("ePue(int9 9 s6;
s1.push(1); s1.push(3);
cout (( s1.top() (( en"l;
s1.pop();
cout (( s1.si<e() (( en"l;
s1.e'pty()8 cout (( )e'pty) : cout (( )not e'pty);
0utputH ,
.
not empty
top returns the element on the top of the stac8< pop removes the top element from the stac8.
&or comparison of t6o stac8s< operator== and operator( are defined.
@ueue. A 9ueue can be instantiated 6ith a list or a "ePue.
Pueue(list(int9 9 P1;
Pueue("ePue(int9 9 P+;
Its public member functions are e'pty< si<e< &ront< bacL< push and pop. &ront returns the
ne5t element from the 9ueue< pop removes this element. bacL returns the last element pushed
to the 9ueue 6ith push. As 6ith the stac8< t6o 9ueues can be compared using operator==
and operator(.
9riority =ueue. A priority 9ueue can be instantiated 6ith a vector or a "ePue. A priority
9ueue holds the elements added by push sorted by using a function obBect co'p of type
.o'pare.
EE use less as co'pare ob;ect
priority_Pueue(vector(int9, less(int9 9 pP1;
EE use !reater as co'pare ob;ect
priority_Pueue("ePue(int9, !reater(int9 9 pP+;
vector v(6, 1);
EE create a priority_Pueue out o& a vector, use less as co'pare ob;ect
priority_Pueue("ePue(int9, less(int9 9 pP6 (v.be!in(), v.en"() );
top returns the element 6ith the highest priority< pop removes this element. The element 6ith
the highest priority is determined by the sorting order imposed by co'p. 2ote< that a priority
9ueue internally is implemented using a heap. So< 6hen less is used as compare obBect< the
element 6ith the highest priority h 6ill be one of the elements for 6hich the follo6ing
condition holdsH less (h, x) == &alse for all elements x in the priority 9ueue.
Additionally< the member functions e'pty and si<e are provided. 2ote that no comparison
operators for priority 9ueues are provided. &or the implementations of the container adaptors<
read D#E< %%.%.
4.4.2 Iterator *daptors
>
To use a stacL < Pueue or priority_Pueue include stacL.h
STL Tutorial page 42 Johannes Weidl
Ae(er"e +terator". &or the bidirectional and random access iterators corresponding reverse
iterator adaptors that iterate through a data structure in the opposite direction are provided.
list(int9 l;
EE &ill l $ith 1 + 6 ,
reverse_bi"irectional_iterator
10
(list(int9::iterator,
list(int9::value_type,
list(int9::re&erence_type,
list(int9::"i&&erence_type9 r (l.en"());
cout (( r (( ) );
rJJ;
cout (( r (( ) );
r KK;
cout (( r;
0utputH : < :
list(int9 l;
EE &ill l $ith 1 + 6 ,
copy (reverse_iterator(int, int, int&, ptr"i&&_t9 (l.en"()),
reverse_iterator(int, int, int&, ptr"i&&_t9 (l.be!in()),
ostrea'_iterator(int9 (cout, ) )) );
0utputH : < 1 .
&or all the se9uence containers @vector< list and "ePueA the member functions rbe!in and
ren" are provided< 6hich return the appropriate reverse iterators.
list(int9 l;
EE &ill l $ith 1 + 6 ,
copy (l.rbe!in(), l.ren"(), ostrea'_iterator(int9 (cout, ) )));
0utputH : < 1 .
+n"ert +terator". A 8ind of iterator adaptors< called insert iterators< simplify the insertion into
containers. The principle is that 6riting a value to an insert iterator inserts this value into the
container out of 6hich the insert iterator 6as constructed. To define the position< 6here the
value is inserted< three different insert iterator adaptors are providedH
bacL_insert_iterator
&ront_insert_iterator
insert_iterator
bacL_insert_iterator and &ront_insert_iterator are constructed out of a container
and insert elements at the end and at the beginning of this container< respectively. A
bacL_insert iterator re9uires the container out of 6hich it is constructed to have
push_bacL defined< a &ront_insert_iterator correspondingly re9uires push_&ront.
"ePue(int9 ";
bacL_insert_iterator("ePue(int9 9 bi (");
&ront_insert_iterator("ePue(int9 9 &i (");
insert_iterator is constructed out of a container and an iterator i< before 6hich the values
6ritten to the insert iterator are inserted.
"ePue(int9 ";
%/
To use reverse_bi"irectional_iterator or reverse_iterator include iterator.h
STL Tutorial page 43 Johannes Weidl
insert_iterator("ePue(int9 9 i (", ".en"() );
Insert iterators satisfy the re9uirements of output iterators< that means that an insert iterator
can al6ays be used 6hen an output iterator is re9uired. operator returns the insert iterator
itself.
The three functions bacL_inserter< &ront_inserter and inserter return the appropriate
insert iterators.
te'plate (class .ontainer9
bacL_insert_iterator(.ontainer9 bacL_inserter(.ontainer& x) {
return bacL_insert_iterator(.ontainer9(x);
}
te'plate (class .ontainer9
&ront_insert_iterator(.ontainer9 &ront_inserter(.ontainer& x) {
return &ront_insert_iterator(.ontainer9(x);
}
te'plate (class .ontainer, class @terator9
insert_iterator(.ontainer9 inserter(.ontainer& x, @terator i) {
return insert_iterator(.ontainer9(x, .ontainer::iterator(i));
}
i&strea' & ()exa'ple)); EE &ile exa'ple: 1 6
"ePue(int9 ";
copy (istrea'_iterator(int, ptr"i&&_t9(&),
istrea'_iterator(int, ptr"i&&_t9(),
bacL_inserter(") );
vector(int9 $ (+,Q);
copy ($.be!in(), $.en"(), &ront_inserter (") );
insert_iterator("ePue(int9 9 i = inserter (", JJ".be!in() );
i = 4;
0uptutH > - > . <
Aa: Stora*e +terator. A ra$_stora!e_iterator enables algorithms to store results into
uninitiali"ed memory.
vector(int9 a (+, 3);
vector(int9 b (+, Q);
int c = allocate((ptr"i&&_t) a.si<e(), (int)0 );
trans&or' ( a.be!in(), a.en"(), b.be!in(),
ra$_stora!e_iterator(int, int9 (c), plus(int9() );
copy (&c=0>, &c=+>, ostrea'_iterator(int9 (cout, ) )) );
0utputH .1 .1
The function allocate is provided by the ST, allocator @see ).3A< trans&or' is an algorithm
of group # @see ).$.#A. To use a ra6 storage iterator for a given type 5< a construct function
must be defined< 6hich puts results directly into uninitiali"ed memory by calling the
appropriate copy constructor. The follo6ing construct function is provided by ST,H
STL Tutorial page 44 Johannes Weidl
te'plate (class 51, class 5+9
inline voi" construct(51 p, const 5+& value) {
ne$ (p) 51(value);
}
int a=10> = {1, +, 6, ,, 3};
copy (&a=0>, &a=3>, ra$_stora!e_iterator(int, int9 (&a=3>) );
4.4.3 "unction *daptors
0e*ator". The negators not1 and not+ are functions 6hich ta8e a unary and a binary
predicate< respectively< and return their complements.
te'plate (class Tre"icate9
unary_ne!ate(Tre"icate9 not1(const Tre"icate& pre") {
return unary_ne!ate(Tre"icate9(pre");
}
te'plate (class Tre"icate9
binary_ne!ate(Tre"icate9 not+(const Tre"icate& pre") {
return binary_ne!ate(Tre"icate9(pre");
}
The classes unary_ne!ate and binary_ne!ate only 6or8 6ith function obBect classes 6hich
have argument types and result type defined. That means< that Tre"icate::ar!u'ent_type
and Tre"icate::result_type for unary function obBects and
Tre"icate::&irst_ar!u'ent_type< Tre"icate::secon"_ar!u'ent_type and
Tre"icate::result_type for binary function obBects must be accessible to instantiate the
negator classes.
vector(int9 v;
EE &ill v $ith 1 + 6 ,
sort (v.be!in(), v.en"(), not+ (less_ePual(int9()) );
0utputH : < 1 .
Binder". GThe binders bin"1st and bin"+n" ta8e a function obBect & of t6o arguments and a
value x and return a function obBect of one argument constructed out of & 6ith the first or
second argument correspondingly bound to x.G< D#E<%%.$.#. Imagine that there is a container
and you 6ant to replace all elements less than a certain bound 6ith this bound.
vector(int9 v;
EE &ill v $ith , 7 10 6 16 +
int boun" = 3;
replace_i& (v.be!in(), v.en"(), bin"+n" (less(int9(), boun"), boun");
EE v: 3 7 10 3 16 3
bin"+n" returns a unary function obBect less that ta8es only one argument< because the
second argument has previously been bound to the value boun". 1hen the function obBect is
applied to a dereferenced iterator i< the comparison i ( boun" is done by the function*call
operator of less.
,daptor" for pointer" to function". The ST, algorithms and adaptors are designed to ta8e
function obBects as arguments. If a usual (.. function shall be used< it has to be 6rapped in a
function obBect.
STL Tutorial page 4 Johannes Weidl
The function ptr_&un ta8es a unary or a binary function and returns the corresponding
function obBect. The function*call operator of these function obBects simply calls the function
6ith the arguments provided.
&or e5ample< if a vector of character pointers is to be sorted le5icographically 6ith respect to
the character arrays pointed to< the binary (.. function strc'p can be transformed into a
comparison obBect and can so be used for sorting.
vector(char9 v;
char c1 = ne$ char=+0>; strcpy (c1, )5i'));
char c+ = ne$ char=+0>; strcpy (c+, ).harles));
char c6 = ne$ char=+0>; strcpy (c6, )Aaron));
v.push_bacL (c1); v.push_bacL (c+); v.push_bacL (c6);
sort (v.be!in(), v.en"(), ptr_&un (strc'p) );
copy (v.be!in(), v.en"(), ostrea'_iterator(char9 (cout, ) )) );
0utputH Aaron Charles Tim
0ote? The above e5ample causes memory lea8s< because the memory allocated 6ith ne$ is
not automatically deallocated. See section ).3 for a solution.
4. *llocators and $e$or- handling
G0ne of the common problems in portability is to be able to encapsulate the information about the
memory model.G< D#E< ;. This information includes the 8no6ledge of
pointer types
type of their difference @difference type ptr"i&&_tA
type of the si"e of obBects in a memory model @si"e type si<e_tA
memory allocation and deallocation primitives.
ST, provides allocators 6hich are obBects that encapsulate the above information. As mentioned in
section ).%.%< all the ST, containers are parametri"ed in terms of allocators. So< containers donJt have
any memory model information coded inherently but are provided 6ith this information by ta8ing an
allocator obBect as argument.
The idea is that changing memory models is as simple as changing allocator obBects. The allocator
allocator< 6hich is defined in "e&alloc.h< is used as default allocator obBect. The compiler vendors
are e5pected to provide allocators for the memory models supported by their product. So< for -orland
(.. allocators for different memory models are provided @see $.#A.
&or every memory model there are corresponding allocate< "eallocate< construct and "estroy
template functions defined. allocate returns a pointer of type 5 to an allocated buffer< 6hich is no
less than nsi<eo&(5).
te'plate (class 59
inline 5 allocate(ptr"i&&_t si<e, 5);
"eallocate frees the buffer allocated by allocate.
te'plate (class 59
inline voi" "eallocate(5 bu&&er);
STL Tutorial page 4! Johannes Weidl
construct puts results directly into uninitiali"ed memory by calling the appropriate copy constructor.
te'plate (class 51, class 5+9
inline voi" construct(51 p, const 5+& value) {
ne$ (p) 51(value);
}
"estroy calls the destructor for a specified pointer.
te'plate (class 59
inline voi" "estroy(5 pointer) {
pointerK9V5();
}
If you have a container of pointers to certain obBects< the container destructor calls a special destroy
function to call all the single pointer destructors and free the memory allocated. To ma8e this 6or8
under -orland (..< a template speciali"ation must be provided.
class 'y_int {
public:
'y_int (int i = 0) { ii = ne$ int(i); }
V'y_int () { "elete ii; }
private:
int ii;
};
EE the &ollo$in! te'plate speciali<ation is necessary $hen usin! Iorlan" .JJ
inline voi" "estroy ('y_int pointer) {
(pointer)K9V'y_int();
}
voi" 'ain (voi") {
vector('y_int9 v (10);
&or (int i = 0; i ( 10; iJJ) { v=i> = ne$ 'y_int(i); }
EE allocate" 'y_int 'e'ory an" vector v are "estroye" at en" o& scope
}
1hen you use a container of pointers to obBects 6hich do not have an e5plicit destructor defined< a
function li8e seP_"elete can be implemented to free all the memory allocated.
te'plate (class Dor$ar"@terator9
inline voi" seP_"elete (Dor$ar"@terator &irst, Dor$ar"@terator last) {
$hile (&irst 2= last) "elete &irstJJ;
}
vector(char9 v;
char c1 = ne$ char=+0>; strcpy (c1, )5i'));
char c+ = ne$ char=+0>; strcpy (c+, ).harles));
v.push_bacL (c1); v.push_bacL (c+);
seP_"elete (v.be!in(), v.en"() );
EE vector v is "estroye" at the en" o& scope
STL Tutorial page 4% Johannes Weidl
The re$aining STL co$ponents
The remaining ST, components and topics not dealt 6ith yet 6ill be described here.
5.1 :o, co$ponents ,or; together
To ma8e it clear ho6 all ST, components 6or8 together the relations bet6een the components
are topic of this section.
(ontainers store obBects of arbitrary types. (ontainers are parametri"ed by allocators.
Allocators are obBects 6hich encapsulate information about the memory model used. They
provide memory primitives to handle memory accesses uniformly. 4very memory model has
its characteristic< tailor*made allocator. (ontainers use allocators to do their memory accesses.
A change of the memory model used leads to a change of the allocator obBect given as an
argument to the container. This means< that on the code level a container obBect is invariant
under different memory models.
An algorithm is a computation order. So< t6o algorithms should differ in the computations
done by them< not in the access method used to read input data and 6rite output data. This can
be achieved 6hen data is accessed in a uniform manner. ST, provides a uniform data access
mechanism for its algorithms * iterators. Different iterators provide different access modes.
The basic input and output unit is the range< 6hich is a 6ell*defined se9uence of elements.
&unction obBects are used in combination 6ith algorithms to encapsulate< for e5ample<
predicates< functions and operations to e5tend the algorithmsJ utility.
Adaptors are interface mappings< they implement ne6 obBects 6ith different or enhanced
functionality on the basis of e5isting components.
It has to be said that this decomposition of the component space is arbitrary to a certain e5tent
but designed to be as orthogonal as possible. This means that interferences bet6een
components are reduced as far as possible.
The clean< orthogonal and transparent design of the library shall help to
simplify application design and redesign
decrease the lines of code to be 6ritten
increase the understandability and maintainability
provide a basis for standard certifying and 9uality assurance as in other areas of system
architecture< design and implementation.
5.2 7ector
Additionally to the member functions described in section ).%.%< a reserve member function
is provided< 6hich informs the vector of a planned change in si"e. This enables the vector to
manage the storage allocation accordingly. reserve does not change the si"e of the vector and
reallocation happens if and only if the current capacity is less than the argument of reserve.
voi" reserve(si<e_type n);
After a call of reserve< the capacity @i.e. the allocated storageA of the vector is greater or
e9ual to the argument of reserve if reallocation has happened< e9ual to its previous value
other6ise. This means< that if you use reserve 6ith a value greater than the actual value of
capacity< reallocation happens and after6ards< the capacity of the vector is greater or e9ual to
the value given as argument to reserve.
To ma8e it clear< 6hy such a member function is provided< remember that reallocation
invalidates all the references< pointers and iterators referring to the elements in the se9uence.
The use of reserve guarantees that no reallocation ta8es place during the insertions that
happen after a call of reserve until the time 6hen the si"e of the vector reaches the capacity
caused by the call of reserve.
STL Tutorial page 4& Johannes Weidl
1ith this in mind< ta8e a loo8 at e5ercise ).%.%. 1e decided to use a list for storing the single
GbitsG< because inserting into a list never invalidates any of the iterators to this container<
6hich 6as essential for the bit*stuff algorithm to 6or8. 2o6< 8no6ing of the e5istence of
reserve< 6e can use this member function to reserve a certain vector capacity and are so in a
position to use a vector as 6ell. After the call of reserve< 6e can insert elements into the
vector till capacity is reached being sure that no reallocation 6ill happen. The argument n of
reserve has to be computed by considering a ma5imum number of bits to be bit*stuffed and
the 6orst case e5pansion< 6hich happens 6hen bit*stuffing a se9uence only consisting of 1Js.
.3 List
Unli8e a vector< a list doesnJt provide random access to its elements. So< the member functions
be!in< en"< rbe!in and ren" return bidirectional iterators. In addition to the member
functions push_bacL and pop_bacL< list provides push_&ront and pop_&ront to add and
remove an element at its beginning< because these operations can be done in constant time.
The container list provides special mutative operations. It is possible to splice t6o lists into
one @member functionH spliceA< that is to insert the content of one list before an iterator
position of another. T6o lists can be merged @'er!eA into one using operator( or a compare
function obBect< a list can be reversed @reverseA and sorted @sortA. It is also possible to
remove all but first element from every consecutive group of e9ual elements @uniPueA.
&or an e5act description of all these member functions read D#E< ?.%.#.
5.4 4e<ue
As a vector< a de9ue supports random access iterators. -ut in addition to the vector< 6hich
only allo6s constant time insert and erase operations at the end< a de9ue supports the constant
time e5ecution of these operations at the end as 6ell as at the beginning. Insert and erase in
the middle ta8e constant time.
-ecause of these constant insert and erase operations at the beginning< a de9ue provides the
member functions push_&ront and pop_&ront. 2ote< that insert< push< erase and pop
invalidate all the iterators and references to the de9ue.
&urther information concerning the de9ue can be found in D#E< ?.%.$.
5.5 Iterator Tags
4very iterator i must have an e5pression iterator_ta!(i) defined< 6hich returns the most
spe!i$i! category tag that describes its behaviour.
The available iterator tags areH input_iterator_ta!, output_iterator_ta!,
&or$ar"_iterator_ta!, bi"irectional_iteerator_ta!,
ran"o'_access_iterator_ta!.
The most specific iterator tag of a built in pointer 6ould be the random access iterator tag.
te'plate (class 59
inline ran"o'_access_iterator_ta! iterator_cate!ory (const 5) {
return ran"o'_access_iterator_ta!();
}
A user defined iterator 6hich satisfies< for e5ample< the re9uirements of a bidirectional iterator
can be included into the bidirectional iterator category.
te'plate (class 59
STL Tutorial page 4( Johannes Weidl
inline bi"irectional_iterator_ta! iterator_cate!ory (const *y@terator(59&)
{
return bi"irectional_iterator_ta!();
}
Iterator tags are used as Gcompile time tags for algorithm selectionG< D#E< 3.:. They enable the
compiler to use the most efficient algorithm at compile time.
Imagine the template function binary_search 6hich could be designed to 6or8 6ith
bidirectional iterators as 6ell as 6ith random access iterators. To use the tag mechanism< the
t6o algorithms should be implemented as follo6sH
te'plate(class Ii"irectional@terator, class 59
Ii"irectional@terator binary_search (Ii"irectional@terator &irst,
Ii"irectional@terator last,
const 5& value,
bi"irectional_iterator_ta!) {
EE 'ore !eneric, but less e&&icient al!orith'
}
te'plate(class Nan"o'Access@terator, class 59
Nan"o'Access@terator binary_search (Nan"o'Access@terator &irst,
Nan"o'Access@terator last,
const 5& value,
ran"o'_access_iterator_ta!) {
EE 'ore e&&icient, but less !eneric al!orith'
}
To use binary'search< a 8ind of stub function has to be 6rittenH
te'plate(class Ii"irectional@terator, class 59
inline Ii"irectional@terator binary_search (Ii"irectional@terator &irst,
Ii"irectional@terator last,
const 5& value) {
binary_search (&irst, last, value, iterator_cate!ory(&irst));
}
At compile time< the compiler 6ill choose the most efficient version of binary_search. The
tag mechanism is fully transparent to the user of binary_search.
.! *ssociati+e Containers
GAssociative containers provide an ability for fast retrieval of data based on 8eys.G< D#E< ?.#.
Associative containers< li8e se9uence containers< are used to store data. -ut in addition to that
associative containers are designed 6ith an intention to optimi"e the retrieval of data by
organi"ing the single data records in a speciali"ed structure @e.g. in a treeA using 8eys for
identification. The library provides four different 8inds of associative containersH set<
'ultiset< 'ap and 'ulti'ap.
set and 'ap support 'ni0'e "eys< that means that those containers may contain at most one
element @data recordA for each 8ey. 'ultiset and 'ulti'ap support e0'al "eys< so more than
one element can be stored for each 8ey. The difference bet6een set @'ultisetA and 'ap
@'ulti'apA is that a set @'apA stores data 6hich inherently contains the 8ey e5pression. 'ap
@'ulti'apA stores the 8ey e5pression and the appropriate data separately< i.e. the 8ey has not
to be part of the data stored.
Imagine 6e have obBects that encapsulate the information of an employee at a company. An
employee class could loo8 li8e thisH
STL Tutorial page ) Johannes Weidl
class e'ployee_"ata {
public:
e'ployee_"ata() : na'e ())), sLill(0), salary(0) {}
e'ployee_"ata(strin! n, int s, lon! sa) :
na'e (n), sLill (s), salary (sa) {}
strin! na'e;
int sLill;
lon! salary;
&rien" ostrea'& operator(( (ostrea'& os, const e'ployee_"ata& e);
};
ostrea'& operator(( (ostrea'& os, const e'ployee_"ata& e) {
os (( )e'ployee: ) (( e.na'e (( ) ) (( e.sLill (( ) ) (( e.salary;
return os;
}
If 6e 6ant to store employee data in a set @'ultisetA< the 8ey has to be included in the
obBect storedH
class e'ployee {
public:
e'ployee (int i, e'ployee_"ata e) :
i"enti&ication_co"e (i), "escription (e) {}
int i"enti&ication_co"e; EE Ley expression to i"enti&y an e'ployee
e'ployee_"ata "escription;
bool operator( (const e'ployee& e) const {
return i"enti&ication_co"e ( e.i"enti&ication_co"e; }
};
2o6 6e are able to declare a set @'ultisetA of employeesH
set
11
(e'ployee, less(e'ployee9 9 e'ployee_set;
'ultiset
1+
(e'ployee, less(e'ployee9 9 e'ployee_'ultiset;
Using a set @'ultisetA< e'ployee is both the "ey type and the val'e type of the set
@'ultisetA.
All associative containers are parametri"ed on a class Wey< 6hich is used to define Ley_type<
and a so*called !omparison ob*e!t of class .o'pare< for e5ampleH
%%
To use a set include set.h
%#
To use a multiset include 'ultiset.h
STL Tutorial page 1 Johannes Weidl
te'plate (class Wey, class .o'pare = less(Wey9,
te'plate (class H9 class Allocator = allocator9
class set {
type"e& Wey Ley_type;
type"e& Wey value_type;
...
};
If 6e 6ant to store employee data in a 'ap @'ulti'apA< the 8ey type is int and the value type
is pair(const int, e'ployee_"ata9H
'ap
16
(int, e'ployee_"ata, less(int9 9 e'ployee_'ap;
'ulti'ap
1,
(int, e'ployee_"ata, less(int9 9 e'ployee_'ulti'ap;
te'plate (class Wey, class 5, class .o'pare = less(Wey9,
te'plate (class H9 class Allocator = allocator9
class 'ap {
type"e& Wey Ley_type;
type"e& pair(const Wey, 59 value_type;
...
};
T6o 8eys L1 and L+ are considered to be e9ual if for the comparison obBect co'p< co'p(L1,
L+) == &alse && co'p(L+, L1) == &alse< so e9uality is imposed by the comparison
obBect and not by operator==.
The member function Ley_co'p returns the comparison obBect out of 6hich the associative
container has been constructed. value_co'p returns an obBect constructed out of the
comparison obBect to compare values of type value_type. All associative containers have the
member functions be!in< en"< rbe!in< ren"< e'pty< si<e< 'ax_si<e and s$ap defined.
These member functions are e9uivalent to the appropriate se9uence container member
functions. An associative container can be constructed by specifying no argument @less(Wey9
is used as default comparison obBectA or by specifying a comparison obBect. It can be
constructed out of a se9uence of elements specified by t6o iterators or another associative
container. operator= @assignment operatorA is defined for all associative containers.
Associative containers provide bidirectional iterators.
2o6 6e 6ant to store some employee data in the set. 1e can use the insert member
functionH
e'ployee_"ata e"1 ();ohn), 1, 3000);
e'ployee_"ata e"+ ()to'), 3, +000);
e'ployee_"ata e"6 ()'ary), +, 6000);
e'ployee e1 (1010, e"1);
e'ployee e+ (+0+0, e"+);
e'ployee e6 (6060, e"6);
pair(set (e'ployee, less(e'ployee9 9::iterator, bool9
result = e'ployee_set.insert (e1);
i& (result.secon") cout (( )insert oL); else cout (( )not inserte");
cout (( en"l (( (result.&irst)."escription.na'e (( en"l;
result = e'ployee_set.insert (e1);
i& (result.secon") cout (( )insert oL); else cout (( )not inserte");
%$
To use a map include 'ap.h
%)
To use a multimap include 'ulti'ap.h
STL Tutorial page 2 Johannes Weidl
pair('ap (int, e'ployee_"ata, less(int9 9::iterator, bool9
result1 = e'ployee_'ap.insert ('aLe_pair (1010, e"1));
'ultiset (e'ployee, less(e'ployee9 9::iterator
result+ = e'ployee_'ultiset.insert (e1);
'ulti'ap (int, e'ployee_"ata, less(int9 9::iterator
result6 = e'ployee_'ulti'ap.insert ('aLe_pair (1010, e"1));

0utputH insert o"
*ohn
not inserted
0ote? &or users of -orland (.. it has to be said that the above map and multimap insert
operations can only be compiled 6ith a change in the code in 'ap.h and 'ulti'ap.h.
Instead of Gtype"e& pair(const Wey, 59 value_typeG I used Gtype"e&
pair(Wey, 59 value_typeG.
insert ta8es an obBect of type value_type and returns a pair consisting of an iterator and a
bool value. The bool value indicates 6hether the insertion too8 place. In case of an associative
container supporting uni9ue 8eys< the iterator points to the element 6ith the 8ey e9ual to the
8ey of the element specified as argument< in case of an associative container supporting e9ual
8eys to the ne6ly inserted element. insert does not affect the validity of iterators and
references to the container.
A second version of insert ta8es a range specified by t6o iterators and inserts the
appropriate elements into the associative container @the return value is voi"AH
pair(int, e'ployee_"ata9 a=+> = { 'aLe_pair (+0+0, e"+),
'aLe_pair (6060, e"6) };
e'ployee_'ap.insert (&a=0>, &a=+>);
The &in" member function ta8es a 8ey value and returns an iterator< 6hich indicates the
success of the search operationH
'ap (int, e'ployee_"ata, less(int9 9::const_iterator i
= e'ployee_'ap.&in" (6060);
i& (i == e'ployee_'ap.en"() ) cout (( )not &oun");
else cout (( (i).secon".na'e;
0utputH mary
'ap is the only associative container 6ith provides the subscribe operator @oprator=>A to
address elements directlyH
e'ployee_"ata " = e'ployee_'ap=+0+0>;
cout (( ";
0utputH tom , 1999
The erase member function can ta8e a value of type Ley_type< a single iterator or a range
specifying the element or elements to be erasedH
e'ployee_'ap.erase (6060);
e'ployee_'ap.erase (e'ployee_'ap.be!in() );
e'ployee_'ap.erase (e'ployee_'ap.be!in(), e'ployee_'ap.en"() );
i& (e'ployee_'ap.e'pty() ) cout (( )e'ployee_'ap is e'pty);
0utputH employee3map is empty
STL Tutorial page 3 Johannes Weidl
erase invalidates only the iterators and references to the erased elements.
Since it doesnJt ma8e sense to store more than one employee under an employee 8ey< for the
demonstration of an associative container supporting e9ual 8eys a slightly different e5ample is
used. A number of employees is stored under the same 8ey 6hich represents a department
code. 1e can use the e'ployee_'ulti'ap container declared earlier in this sectionH
EE e'ployee_'ulti'ap is e'pty
e'ployee_'ulti'ap.insert ('aLe_pair(101, e"1)); EE "epart'ent co"e 101
e'ployee_'ulti'ap.insert ('aLe_pair(101, e"+));
e'ployee_'ulti'ap.insert ('aLe_pair(10+, e"6)); EE "epart'ent co"e 10+
count ta8es a 8ey value and returns the number of elements stored under this 8ey value.
'ulti'ap (int, e'ployee_"ata, less(int9 9::si<e_type count
= e'ployee_'ulti'ap.count (101);
cout (( count;
0utputH 1
lo$er_boun" (L) 6ith L of type Ley_type returns an iterator pointing to the first element
6ith 8ey not less than L. upper_boun" (L) returns an iterator pointing to the first element
6ith 8ey greater than L. ePual_ran!e (L) returns a pair of iterators 6ith the first iterator
being the return value of lo$er_boun" (L) and the second being the return value of
upper_boun" (L).
ostrea'& operator(( (ostrea'& os, const pair(int, e'ployee_"ata9& p) {
os (( )e'ployee: ) (( p.secon".na'e (( ) ) (( p.secon".sLill (( ) ) ((
p.secon".salary;
return os;
}
type"e& 'ulti'ap (int, e'ployee_"ata, less(int9 9::iterator ;;
pair(;, ;9 result = e'ployee_'ulti'ap.ePual_ran!e (101);
copy (result.&irst,
result.secon",
ostrea'_iterator(pair(int, e'ployee_"ata9 9 (cout , )Mn)) );
0utputH *ohn . ,999
tom , 1999
STL Tutorial page 4 Johannes Weidl
! Cop-right
The spell*chec8er e5ample from section ).$ is a (opyright %>>3 of . !a"ayeri and G.Trausmuth * TU
1ien.
All code pieces 6ith a shaded frame are subBect to the follo6ing copyright notice by 7e6lett Pac8ardH
E

.opyri!ht (c) 144,
0e$lettKTacLar" .o'pany

Ter'ission to use, copy, 'o"i&y, "istribute an" sell this so&t$are
an" its "ocu'entation &or any purpose is hereby !rante" $ithout &ee,
provi"e" that the above copyri!ht notice appear in all copies an"
that both that copyri!ht notice an" this per'ission notice appear
in supportin! "ocu'entation. 0e$lettKTacLar" .o'pany 'aLes no
representations about the suitability o& this so&t$are &or any
purpose. @t is provi"e" )as is) $ithout express or i'plie" $arranty.

E
This tutorial is permitted to be used for academic and teaching purposes in 6hole or in part if the
follo6ing copyright notice is preservedH
(opyright %>>3< %>>: !ohannes 1eidl * TU 1ien
All other use< especially if commercial< can only be granted by the author himself * feel free to contact
me.
% Literature
D%E Stroustrup< -BarneH The (.. programming language ** #nd ed.
!une< %>>$
D#E ,ee< engT Stepanov< Ale5H The Standard Template ,ibrary
7P ,abaratories< %3/% Page ill +oad< Palo Alto< (A >)$/)
&ebruary ;< %>>3
D$E ST,..
The 4nhanced Standard Template ,ibrary< Tutorial I +eference anual
odena Soft6are Inc.< #$: 2. Santa (ru" Ave< Suite #%$< ,os Gatos (A >3/$/
%>>)
D)E Standard Template ,ibrary +eference
+ensselaer Polytechnic Institute< %>>)
includes as chapter :
The ST, 0nline Algorithm +eference
(oo8< +obert !r.T usser< David +.T Pale6s8i< Lenneth !.
online at httpHCC666.cs.rpi.eduCmusserCstl.html
STL Tutorial page Johannes Weidl

Вам также может понравиться