Vous êtes sur la page 1sur 56

La bibliothque standard du C++

Par Bruno Garcia


Date de publication : 1 janvier 1999

La librairie standard du C++ est ne de la volont d'apporter aux programmeurs C++ un


canevas de programmation efficace, gnrique et simple utiliser.
Remarque : cet article date de 1999 et les informations qu'il contient sont en partie
obsoltes. N'hsitez pas poser des questions sur le forum en cas de doute :

La bibliothque standard du C++ par Bruno Garcia

I - Rappels historiques.................................................................................................................................................4
II - Les fondamentaux..................................................................................................................................................5
II-A - Espaces de nommage.................................................................................................................................. 5
II-A-1 - Motivation..............................................................................................................................................5
II-A-2 - Proprits..............................................................................................................................................5
II-A-3 - Mise en oeuvre des espaces de nommage.........................................................................................5
II-A-3-a - Dclaration et dfinition............................................................................................................... 5
II-A-3-b - Accs aux membres.................................................................................................................... 6
II-A-3-b-i - Les noms qualifis................................................................................................................6
II-A-3-b-ii - La clause using namespace................................................................................................7
II-A-3-b-iii - La clause using identificateur............................................................................................. 8
II-A-3-b-iv - Conclusion sur l'accs aux membres et alias d'espaces de nommage..............................9
II-A-4 - Un exemple plus complet...................................................................................................................10
II-A-5 - La STL et les espaces de nommage................................................................................................. 12
II-B - Quelques points connatre.......................................................................................................................12
II-B-1 - La portabilit de la STL......................................................................................................................12
II-B-2 - Les fichiers d'entte utiliss par la STL............................................................................................. 12
II-C - Les chanes de caractres......................................................................................................................... 13
II-C-1 - Construction de variables du type string, conversion avec................................................................13
II-C-2 - Les oprations de routine.................................................................................................................. 14
II-C-2-a - Accs aux caractres................................................................................................................ 14
II-C-2-b - Longueur d'une chane.............................................................................................................. 14
II-C-2-c - Affectations, ajouts, changes de caractres............................................................................ 14
II-D - Les exceptions de la STL...........................................................................................................................15
II-D-1 - La classe exception............................................................................................................................15
II-D-2 - La hirarchie des exceptions de la STL............................................................................................ 16
II-D-3 - Exemple d'utilisation des exceptions de la STL.................................................................................17
II-D-4 - Aux utilisateurs de C++ Builder......................................................................................................... 19
II-E - Le Support de la RTTI................................................................................................................................ 20
II-E-1 - Qu'est ce que le RTTI........................................................................................................................ 20
II-E-2 - La classe type_info et l'oprateur typeid............................................................................................20
II-E-3 - Exemple d'utilisation du RTTI.............................................................................................................21
III - Les classes conteneur de la STL....................................................................................................................... 23
III-A - Philosophie gnrale..................................................................................................................................23
III-B - Prsentation des conteneurs..................................................................................................................... 23
III-B-1 - Prsentation des squences lmentaires....................................................................................... 23
III-B-1-a - Les vecteurs..............................................................................................................................23
III-B-1-b - Les listes................................................................................................................................... 24
III-B-1-c - Les DQ...................................................................................................................................... 24
III-B-2 - Les oprations disponibles sur l'ensemble des squences.............................................................. 24
III-B-3 - Oprations spcifiques...................................................................................................................... 26
III-B-3-a - Oprations spcifiques sur les vecteurs...................................................................................26
III-B-3-b - Oprations spcifiques sur les listes........................................................................................ 29
III-B-3-c - Oprations spcifiques sur les DQ........................................................................................... 34
III-B-4 - Itrateurs et squences lmentaires............................................................................................... 34
III-B-5 - Les utilisations spcialises des squences lmentaires............................................................... 34
III-B-5-a - Aspects gnraux..................................................................................................................... 34
III-B-5-b - Les files (queues)..................................................................................................................... 35
III-B-5-c - Les piles (stack)........................................................................................................................ 35
III-B-5-d - Exemple sur les piles et les files.............................................................................................. 36
III-B-5-e - Les files priorit..................................................................................................................... 37
III-B-6 - Les conteneurs associatifs................................................................................................................ 39
III-B-6-a - Le type pair...............................................................................................................................40
III-B-6-b - Itrateurs et conteneurs associatifs.......................................................................................... 41
III-B-6-c - Mthodes et fonctions communes aux types set et map..........................................................41
III-B-6-d - Le type ensemble..................................................................................................................... 43
III-B-6-e - Le type map ....................................................................................................................... 44
III-B-6-f - Un exemple de map.................................................................................................................. 44
-2Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

III-B-6-g - Un exemple de multimap..........................................................................................................47


III-C - Les itrateurs............................................................................................................................................. 49
III-C-1 - Dfinition et premier contact............................................................................................................. 49
III-C-2 - Les diffrents types d'itrateurs........................................................................................................ 50
III-C-3 - Comment obtenir un itrateur ?........................................................................................................ 51
III-C-4 - Les itrateurs de flux........................................................................................................................ 51
IV - Annexe A : un exemple de makefile.................................................................................................................. 54
V - Annexe B : Tables des illustrations..................................................................................................................... 56

-3Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

I - Rappels historiques
La librairie standard du C++ est ne de la volont d'apporter aux programmeurs C++ un canevas de programmation
efficace, gnrique et simple utiliser. Celui-ci comprend notamment :

Des classes conteneur gnriques et des algorithmes associs


Une classe string paramtre par le type de caractres qu'elle contient
Une nouvelle famille de classes flux (iostream).

Autrefois connue sous le nom de STL (Standard Template Library) - avant l'adjonction de la nouvelle classe chanes
et des bibliothques de flux tendues-, la Librairie Standard du C++ reprend nombre des caractristiques de son
anctre.
Le prsent essai n'a pas pour objectif - loin de l - d'tre exhaustif sur le domaine mais uniquement de prsenter les
concepts fondamentaux et quelques exemples (orients Recherche Oprationnelle) d'utilisation de la STL.
Pour clturer cette introduction, je voudrais insister sur l'intrt vident de gnraliser l'utilisation de la STL par
quelques critres directement issus du gnie logiciel.
Fiabilit : les classes de la STL sont particulirement sres, et, ds qu'une erreur est dcouverte, elle est rapidement
corrige1. En outre, la plupart des composants a t crite par des spcialistes, en particulier Andrew Koenig, l'un
des premiers et plus fervents concepteurs / utilisateurs du C++.
Rutilisabilit : la STL tant dornavant totalement intgre au standard du C++, son utilisation est sense garantir
la portabilit du logiciel. Je souhaite nanmoins modrer ds maintenant cette dernire affirmation. En effet, certaines
versions de la STL ne sont pas tout fait au standard et ne garantissent donc pas la portabilit.
Comprhensibilit et maintenabilit : la standardisation de la STL garantit que tout utilisateur sera capable
d'apprhender favorablement du code reposant sur elle.
Efficacit (au sens classique -) : les composants ayant t crits par des matres, il y a fort parier que leur utilisation
conduit du code plus efficace que celui reposant sur des bibliothques maison
Prsenter de manire cohrente la STL est assez difficile. En effet, il est impossible de sparer l'tude des conteneurs
de celle des itrateurs ou des algorithmes tant ces notions sont mles. Aussi, cela contraindra le lecteur des aller
retours frquents dans le texte.

En effet, il est bien connu que plus un composant est utilis, plus il devient sr

-4Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

II - Les fondamentaux
II-A - Espaces de nommage
Cette section dcrit l'une des plus rcentes additions au standard du C++ : les espaces de nommage.

II-A-1 - Motivation
L'une des notions qui manque assurment le plus au C++ est celle de paquetage. Ceci est d'autant plus dsastreux
que mme l'ADA (et, plus rcemment, Java), langage pourtant non orient objet l'origine l'a toujours propos. En
effet, il est dsolant de ne pouvoir rassembler dans un lment du langage un ensemble de classes, de fonctions,
de constantes, de types et de variables traitant du mme concept.
En outre, un paquetage est habituellement nomm et fournit un niveau d'abstraction supplmentaire sur les noms
des entits qu'il contient. En effet, pour accder une entit quelconque d'un paquetage, il convient de prfixer son
nom par celui du paquetage ou bien d'utiliser une clause spciale offrant la visibilit sur l'ensemble des dclarations
du paquetage.
De surcrot, l'utilisation de tels prfixes permet de rsoudre l'un des problmes les plus courants lorsque l'on utilise
diffrentes bibliothques de composants logiciels : les collisions de noms. Les prfixes de noms permettent non
seulement au programmeur d'viter la collision mais galement l'diteur de liens de s'y retrouver.
Les espaces de nommage du C++ pallient partiellement au manque de paquetage. En effet, ils permettent de crer
- comme leur nom l'indique - un groupe d'entits rassembles autour d'un prfixe de nommage.

II-A-2 - Proprits
Les espaces de nommage sont pourvus - entre autres - des proprits remarquables suivantes :
Imbrication : il est possible d'imbriquer les espaces de nommage pour dcouper un concept en sous parties. On
peut ainsi organiser les espaces de nommage du C++ la manire de l'arborescence des paquetages de Java
Dfinition incrmentale : l'ensemble des dclarations et des dfinitions d'un espace de nommage peut s'taler sur
plusieurs fichiers source. En outre, tout utilisateur est autoris rajouter ses propres dclarations et dfinitions dans
un espace de nommage auquel il a accs. Cette facult pouvant alternativement tre vue comme un avantage ou
un inconvnient.
Pas de modification d'accs : contrairement Java ou ADA, il n'y a pas de notion de visibilit de paquetage associ
aux espaces de nommage. En effet, considrons 2 classes A et B appartenant au mme espace de nommage. Si
elles n'ont pas de relation privilgie (hritage ou amiti), les mthodes de A n'ont pas de visibilit particulire sur
les membres de B et rciproquement. Ce dernier point ne peut que laisser un arrire got amer dans la bouche tant
il aurait t intressant de combler cette lacune du C++. Peut-tre dans la prochaine norme ?

II-A-3 - Mise en oeuvre des espaces de nommage


Les prochaines sections dcrivent succinctement l'essentiel de la syntaxe lie aux espaces de nommage. Aprs avoir
tudi la dclaration d'un espace de nommage, nous verrons comment accder aux entits qu'il contient.

II-A-3-a - Dclaration et dfinition


La dclaration d'un espace de nommage se fait par l'utilisation du mot clef namespace. Comme d'habitude avec le
C++, il est possible de faire une dclaration de type forward :
-5Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

namespace identificateur;

La syntaxe de dfinition d'un espace reprend celle d'un bloc du langage


namespace identificateur
{
// liste des entits regroupes dans l'espace de nommage
};

L'exemple suivant montre un espace de nommage regroupant deux classes et une constante :

Programme 2.1 dclaration et dfinition d'un espace de nommage


namespace azedzed
{
class A
{
// dfinition de la classe A
};
const double PI=3.1415927;

class B
{
// dfinition de la classe B
};

II-A-3-b - Accs aux membres


Tout d'abord, il faut savoir que chaque membre d'un mme espace de nommage a une visibilit directe sur les
identificateurs de tout l'espace. Dornavant, nous ne nous intresserons qu' traiter les rgles de visibilit depuis
l'extrieur de l'espace.

II-A-3-b-i - Les noms qualifis


La premire manire d'accder un membre d'un espace de nommage consiste prfixer son nom par celui du
prfixe suivi de l'oprateur de rsolution de porte :: on parle alors de nom qualifi. Par exemple, pour dclarer un
objet obA de la classe ClasseA appartenant l'espace de nommage EspNom1, il faudra utiliser une dclaration
de la forme :
EspNom1::ClasseA *obA;

Considrons dsormais la classe ClasseB dclare dans EspNomInt lui mme imbriqu dans EspNomExt. Pour
accder ClasseB, il faut spcifier tout le chemin de nommage, soit :
EspNomExt::EspNomInt::ClasseB *obB;

Un espace de nommage non imbriqu est dit global ou top-level.

-6Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

II-A-3-b-ii - La clause using namespace


Il est parfois fastidieux d'utiliser des noms qualifis qui peuvent s'avrer trs long. La clause using namespace
permet d'obtenir la visibilit directe sur l'ensemble des entits dclares dans un espace de nommage. La syntaxe
en est la suivante : using namespace identificateur;
Il est important de noter que dans le cas o des espaces de nommage sont imbriqus, la clause using namespace
ne donne qu'un seul niveau de visibilit. En outre, l'utiliser peut de nouveau faire surgir des problmes de collision
de noms, auquel cas, le compilateur vous en avertira.
En effet, considrez le cas suivant :

Programme 2.2 Exemple de collision entrane par l'utilisation de la cause using namespace
namespace A
{
class Erreur // ou tout autre nom courant
{
};
}
namespace B
{
class Erreur // ou taut autre nom courant
{
};
}
class Erreur
{
};
int main(int,char**)
{
Erreur e1; // Pas de probleme quoique ::Erreur e1 eut ete preferable
A::Erreur e2; // Pas de probleme classe Erreur de l'espace A
B::Erreur e3; // Pas de probleme classe Erreur de l'espace B
using namespace A;
Erreur e4; // Ambiguite entre ::Erreur et A::Erreur
using namespace B;
Erreur e5; // ambiguite entre ::Erreur, A::Erreur et B::Erreur
}

return 0;

Autre cas vicieux. Considrez trois espaces de nommage avec les relations indiques par la figure suivante :

-7Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Figure 2.1 Espaces de nommage avec noms conflictuels


Il existe un espace de nommage A, un espace imbriqu A::B et un espace B.
Considrez le fragment de code suivant :
using namespace A; // Ok, dlivre la visibilit sur les lments de A
using namespace B; // ??? est-ce A::B ou bien B?

Le rsultat de la dernire est laiss vrifier en exercice. Il tait possible de lever l'ambigut en prcisant, soit using
namespace A::B soit using namespace ::B pour l'espace de nommage non imbriqu.

II-A-3-b-iii - La clause using identificateur


Il est galement possible d'utiliser la clause using (notez l'absence de namespace aprs using) sur un identificateur
unique d'un espace de nommage pour le rendre accessible directement. Si un autre identificateur de mme nom
existait avant la clause, il est masqu par celui de la clause using, comme l'illustre l'exemple suivant :

Programme 2.3 Exemple d'utilisation de la clause using et des dangers inhrents


#include <iostream>
namespace BASE
{
class ErreurBase
{
public:
virtual void show(void)=0;
};
}
namespace A
{
class Erreur : public BASE::ErreurBase
{
public:
virtual void show(void)
{
cout << " A :: Erreur " << endl;
}
};
}
class Erreur : public BASE::ErreurBase
{
public:
virtual void show(void)
{
cout << " :: Erreur " << endl;
}
};

-8Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Programme 2.3 Exemple d'utilisation de la clause using et des dangers inhrents


int main(int, char**)
{
Erreur e1; // ::Erreur
A::Erreur e2; // A::Erreur
using A::Erreur;
Erreur e3; // A::Erreur masque ::Erreur
e1.show();
e2.show();
e3.show();
}

return 0;

II-A-3-b-iv - Conclusion sur l'accs aux membres et alias d'espaces de nommage


Pour conclure, je ne conseille pas l'utilisation de la clause using sous quelque forme que ce soit car cela nuit
considrablement la clart du code en supprimant l'un des avantages les plus importants de la notion d'espace de
nommage : la non ambigut d'origine avec la possibilit de rintroduire des collisions de nommage.
Certains argueront probablement que les noms d'espace de nommage sont parfois trs longs (notamment dans le
cas d'imbrications multiples). Ce quoi je rpondrai par la possibilit de crer des noms d'alias. Voici la syntaxe :
namespace nomAlias = nomEspaceOriginel ;

Par exemple :
namespace local = EspaceExterne::EspaceInterne::EspacePlusInterne ;

ou encore :

Programme 2.4 Exemple plus complet d'utilisation des alias


#include <iostream>
namespace BASE
{
class ErreurBase
{
public:
virtual void show(void)=0;
};
}
namespace NomTropLong
{
class Erreur : public BASE::ErreurBase
{
public:
virtual void show(void)
{
cout << "NomTropLong :: Erreur " << endl;
}
};
namespace EncorePlusLong
{
class Erreur : public BASE::ErreurBase

-9Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Programme 2.4 Exemple plus complet d'utilisation des alias


{

public:
virtual void show(void)
{
cout << "NomTropLong :: EncorePlusLong :: Erreur " << endl;
}
};

class Erreur : public BASE::ErreurBase


{
public:
virtual void show(void)
{
cout << " :: Erreur " << endl;
}
};
int main(int, char**)
{
namespace A = NomTropLong;
namespace B = A::EncorePlusLong;
// Etant declares a l'interieur de main les noms d'alias
// sont locaux et donc non exportes !
Erreur
e1; // ::Erreur
NomTropLong::Erreur
e2;
NomTropLong::EncorePlusLong::Erreur e3;
A::Erreur
e4; // ni ambigue ni fastidieux !
B::Erreur
e5; // idem
e1.show();
e2.show();
e3.show();
e4.show();
e5.show();
}

return 0;

II-A-4 - Un exemple plus complet


L'exemple de code suivant (incluant plusieurs fichiers source) illustre certaines fonctionnalits des espaces de
nommage :

Dfinition incrmentale
Imbrication des espaces de nommage
Utilisation des alias

Programme 2.5 Exemple complet d'utilisation des espaces de nommage


#ifndef __NameRO_H__
#define __NameRO_H__
//
//
//
//
//

Fichier des dclarations


Dclare un espace de nommage externe (RO)
et deux espaces de nommage internes RO::GRAPHES et
RO::PROGRAMMATION_DYNAMIQUE
Ainsi que des classes

namespace RO
{
- 10 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Programme 2.5 Exemple complet d'utilisation des espaces de nommage


namespace GRAPHES
{
class Graphe
{
// code omis
public:
void afficher(void);
};
class AlgorithmePCC
{
// code omis
public:
void resoudre(void);
};

namespace PROGRAMMATION_DYNAMIQUE
{
class SacADos
{
// code omis
public:
void resoudre(void);
};
}

}
#endif

// Deuxieme fichier : implemente l'une des classes


// Notez que l'on est oblige de recreer l'imbrication des namespace
#include "NameRO.hxx"
namespace RO
{
namespace GRAPHES
{
void Graphe::afficher(void)
{
}
}
}
// Troisieme fichier : suite de l'implementation des classes
// du package RO::GRAPHES
// Notez que l'on est oblige de recreer l'imbrication des namespace
#include "NameRO.hxx"
namespace RO
{
namespace GRAPHES
{
void AlgorithmePCC::resoudre(void)
{
}
}
}
// Quatrieme fichier : implementation de la classe
// du package RO::PROGRAMMATION_DYNAMIQUE
// Notez que l'on est oblige de recreer l'imbrication des namespace
#include "NameRO.hxx"
namespace RO
{
namespace PROGRAMMATION_DYNAMIQUE
{
void SacADos::resoudre(void)
- 11 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Programme 2.5 Exemple complet d'utilisation des espaces de nommage


{
}

// Dernier fichier : main utilisant des alias de namespace


#include "NameRO.hxx"
int main(int, char **)
{
namespace GR=RO::GRAPHES;
namespace DY=RO::PROGRAMMATION_DYNAMIQUE;
GR::Graphe g;
GR::AlgorithmePCC a;
DY::SacADos s;
g.afficher();
a.resoudre();
s.resoudre();
}

return 0;

II-A-5 - La STL et les espaces de nommage


Hormis les noms d'exceptions, tous les identificateurs de la STL sont regroups dans un espace nomm std. Ceci
est particulirement judicieux car l'on y retrouve des noms aussi courants que vector, deque ou string. Vous noterez
que c'est un nom particulirement court qui ne justifie aucunement l'utilisation de la clause usingnamespace.
L'utilisation de clauses type #ifdef permet nanmoins d'utiliser la STL sur les compilateurs non pourvus du support
des espaces de nommage.

II-B - Quelques points connatre


II-B-1 - La portabilit de la STL
Si les fonctionnalits prsentes dans la STL sont normalises, toute la partie implmentation est laisse libre. Par
exemple, le nom des fichiers d'entte peut lgrement varier d'une implmentation l'autre, rendant ncessaire
l'utilisation de clauses #ifdef. Toutefois, les diffrences sont toujours mineures et n'entranent que trs peu de
modifications du code source.
Il est toutefois un point particulier, relatif l'utilisation massive des template pour la description des classes conteneur,
qu'il est ncessaire de souligner. En effet, de nombreuses classes utilisent des paramtres template avec une valeur
par dfaut, fonctionnalit non reconnue par de nombreux compilateurs C++ populaires, en particulier les compilateurs
Borland et GNU.

II-B-2 - Les fichiers d'entte utiliss par la STL


Selon les implmentations, les fichiers d'entte de la STL adoptent l'extension .h ou, aucune extension. En outre, par
convention, l'on utilise jamais d'extension pour invoquer l'entte. En effet, l'utilisation de la classe string, par exemple,
repose sur la directive #include<string> que les dclaration associes soient dans le fichier string.h ou le fichier
string. Cette extension des compilateurs C++ s'avre bien pratique car elle permet de raliser des inclusions sans
connatre l'avance la convention adopte par le fournisseur de la STL que vous aurez utiliser.

- 12 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

II-C - Les chanes de caractres


La STL propose des fonctionnalits volues sur les chanes de caractres.
Celles-ci sont bases sur la classe basic_string, classe template paramtrable par le type de caractres contenus
dans la chane. Deux instances correspondant respectivement aux types caractre 8 bits et caractre 16 bits sont
proposes par dfaut : string et wstring. Le fichier d'entte correspondant est habituellement nomm string ou
string.h. La classe string s'obtenant par simple instanciation de basic_string, nous nous concentrerons sur son tude
dans la suite de cet expos.
Le nombre d'oprations fournies sur les chanes est pour le moins impressionnant. Nous ne donnerons pas ici une
liste exhaustive des possibilits mais seulement quelques oprations particulirement utiles.

II-C-1 - Construction de variables du type string, conversion avec


Il ne faut surtout pas oublier que le type string est une classe et donc, non totalement homomorphe char * bien qu'il
existe des oprations de conversion entre les deux.
Les oprations disponibles pour construire une variable de type string sont les suivantes :

Programme 2.6 Mini exemple de constructeurs de la classe string


string s1;
// Chane vide s1
string s2("Clermont-Ferrand) // Initialisation avec un char *
char tab[]="Auvergne
string s3(tab,4);
// s3==Auve
string s4(s2);
// constructeur par recopie
string s5(s2,8);
// s5==Ferrand
string s6(s2,16);
// s6==Clermont-Ferrand
string s7(s2,18);
// s7==Clermont-Ferrand
string s8(4,'c');
// s8==cccc

A la lecture de cet exemple, plusieurs commentaires s'imposent :

Il est possible de crer des string partir des classiques tableaux de caractres en spcifiant, ou non,
une taille maximale de recopie. Cette conversion peut mme se faire de faon implicite avec certains
compilateurs.
Si le second paramtre dpasse la longueur de la chane, seuls les caractres avant le zro sont copis.
Il n'y a pas de constructeur prenant simplement une taille. Le constructeur par dfaut alloue (dans la plupart
des implmentations) 20 caractres. Cet inconvnient est palli par l'existence d'un constructeur crant une
chane constitue de la rptition de n fois le mme caractre. Il suffit de spcifier \0' comme caractre de
remplissage pour obtenir une chane vide avec capacit choisie par l'utilisateur.
Le constructeur par recopie admet 2 paramtres supplmentaires permettant respectivement de spcifier :

La position de dbut de recopie - le premier caractre est la position 0.

Le nombre de caractres recopier. Si la recopie devait se faire aprs la fin de la chane, seuls les
caractres rellement prsents dans l'original sont effectivement recopis.

La mthode de stockage effectif des chanes de caractres peut varier d'une implmentation l'autre, mais dans la
plupart des cas, elle repose sur l'utilisation d'un tableau de caractres.
Il n'existe pas d'oprateur de conversion implicite depuis string vers char *, car cela permettrait d'effectuer des
oprations malheureuses conduisant des aberrations au niveau de la reprsentation mmoire. Au lieu de cela, la
classe string possde deux mthodes quivalentes nommes c_str et data et renvoyant un const char *. En raison
des particularits de stockage des chanes de caractres sous certains implmentations, il est fortement dconseill
d'effectuer des modifications sur le tableau renvoy aprs un cast supprimant son caractres constant.
- 13 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

La destruction des chanes de caractres se fait via le destructeur de la classe basic_string.

II-C-2 - Les oprations de routine


II-C-2-a - Accs aux caractres
En plus des mthodes c_str et data, et comme l'on peut lgitimement s'y attendre il est tout fait possible d'accder
aux diffrents caractres composant une chane l'aide de l'oprateur d'indexation [].
En outre, il existe la mthode at(int position) qui permet d'effectuer grosso modo la mme opration que l'oprateur
d'indexation. La principale diffrence tient la gestion des dpassements de range.
En effet, l'oprateur [] renvoie une constante prdfinie alors que at lance une exception de type range_error.

II-C-2-b - Longueur d'une chane


Il convient ici de bien faire la diffrence entre la longueur logique de la chane et sa capacit en caractres. La seconde
est physique et rend compte de l'espace allou dans le conteneur de la chane alors que la premire tmoigne du
nombre de caractres rellement prsents.
Pour tablir un parallle, en C la longueur logique serait renvoye par strlen alors que la capacit serait le nombre
de caractres fourni malloc ou plac entre les crochets lors de l'allocation statique d'une chane

size_t length()
size_t size()
size_t capacity()
size_t max_capacity()
bool empty()
void reserve(size_t n)
void resize(size_t n)

void resize(size_t n, char z)

Renvoie la longueur logique d'une


chane de caractres
Synonyme pour length
Capacit d'une chane
Capacit maximale d'une chane :
renvoie un fait la quantit de mmoire
disponible sur le systme
Vrai si la chane ne contient aucun
caractre assimilable au test
(length==0)
Porte la capacit de la chane (si
possible !) n.
Affecte n la longueur de la chane Si
(n < length), il y a troncature Si (length
< n < capacity) il y a ajout d'espaces Si
(n > capacity) la capacit est d'abord
porte n avant ajout d'espaces
Comportement similaire resize
la diffrence que le caractre de
remplissage est spcifi

Tableau 2.1 mthodes agissant sur la taille des chanes de caractres

II-C-2-c - Affectations, ajouts, changes de caractres


La classe basic_string est quipe d'un oprateur d'affectation dont l'implmentation a tendance varier en fonction
du fournisseur. Il agit toujours par recopie du membre de droite vers le membre gauche mais, dans certains cas, il
ne modifie la capacit de la chane cible que lorsque cela s'avre ncessaire.

- 14 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

A mon avis, de nombreux implmenteurs ont cod cet oprateur en utilisant des compteurs de rfrence et des
recopies tardives : seul un pointeur est recopi lors de l'affectation, la structure de donnes sous-jacente n'est
recopie que si l'une des deux chanes est modifie. Cette astuce assure des gains de performance non ngligeables
dans de nombreuses situations et est encourage par, excusez du peu, Scott Meyers et Steve Coplien - ce qui est
bon pour les dieux doit bien l'tre pour nous autres, pauvres mortels !
La classe basic_string dispose de mthodes trs intressantes et d'ordre trs gnral permettant d'ajouter des
squences dans une chane. Nous n'en donnons ici qu'une description assez sommaire.

append

permet d'ajouter tout ou partie


d'une chane argument au bout
de la chane cible
affecte tout ou partie de la chane
argument la chane cible
insre tout ou partie d'une
chane argument une position
spcifie en paramtre dans la
chane cible
change le contenu de la chane
cible avec celui d'une chane
passe en paramtre

assign
insert

swap

Tableau 2.2 les mthodes gnrales d'ajout dans les squences

II-D - Les exceptions de la STL


La STL fournit une panoplie d'exceptions trs complte permettant d'tablir des diagnostiques assez dtaills aux
programmeurs. L'ensemble repose sur la classe de base exception et sur deux classes drives logic_error et
runtime_error.
La classe logic_error et ses drives sont utilises pour signaler des exceptions dues la logique interne d'un
programme, c'est dire finalement des problmes de robustesse du logiciel. En gnral, de telles erreurs sont
prvisibles et peuvent tre facilement vites. Elles sont donc surtout utilises lors de la mise au point de programmes.
En revanche les exceptions issues de runtime_error notifient au programmeur (ou l'utilisateur final si elles ne sont
pas traites) des erreurs lies l'environnement du programme. Ces erreurs sont rarement vitables car parfois non
prvisibles car elle tmoignent de phnomnes divers tels que des problmes de dpassement de prcision infrieur
ou suprieur ou des dfaillances du matriel.

II-D-1 - La classe exception


C'est la classe de base de toutes les exceptions. Elle est dfinie dans le fichier d'entte exception. Bien que ce ne
soit pas une classe virtuelle pure, elle est pourvue de la mthode what dont le code doit tre le suivant :

Programme 2.7 Dclaration de la classe std::exception


class exception
{
// code omis
virtual const char * what () const throw ()
{
return << pointeur vers une chane quelconque >> ;
}
};
- 15 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Programme 2.7 Dclaration de la classe std::exception


Cette mthode est clairement destine tre redfinie par les sous classes d'exception afin de fournir un message
intelligible l'utilisateur et le renseignant sur les causes de l'exception.

II-D-2 - La hirarchie des exceptions de la STL


La figure suivante indique les relations d'hritage entre les classes d'exception de la STL.
Les classes runtime_error et logic_error sont identiques dans leur dclaration : elles ne sont diffrencies que dans
le but de faire un traitement discriminant sur ces deux grandes catgories. A l'inverse de leur anctre commun, leur
constructeur prend un const string & en paramtre (voir ce sujet les sections concernant le type string) qui permet
de rajouter un message explicitant, par exemple, les circonstances prsidant l'erreur.
Vous noterez au passage que les exceptions directement issues de exception utilisent un message sous forme de
const char * alors que les erreurs plus classieuses utilisent des const & string.
Dans certaines implmentations de la STL, l'inclusion de <exception> n'est pas suffisante. Il est galement ncessaire
d'inclure un autre fichier d'enttes nomm <stdexcept>.
Ces diffrentes classes peuvent, bien entendu, tre drives afin de crer de nouvelles exceptions adaptes chaque
cas.

Figure 2.2 Hirarchie des exceptions de la STL


Le tableau suivant reprend ces diverses exceptions en explicitant leur utilisation.

bad_exception

Exceptions directement issues de exception


Dnote un problme de spcification
d'exception. Typiquement, une mthode ou
une fonction a lanc une exception qui n'tait
pas prvue dans sa dclaration. En thorie
le compilateur aurait du s'en apercevoir

- 16 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Autre cas : bad_exception est lance par la


fonction standard unexpected.
bad_alloc
Dclare dans le fichier d'entte new,
l'exception bad_alloc rapporte un problme
d'allocation survenu lors de l'excution de
operator new ou operator [] new.
bad_cast bad_typeid
Dclares dans le fichier d'entte typeinfo,
ces exceptions sont respectivement
leves lors d'une mauvaise utilisation
de dynamic_cast ou la recherche de
typeid(*NULL). A ce dernier sujet, on
consultera avec profit la section consacre
l'tude du RTTI.
Exceptions issues de runtime_error
overflow_error underflow_error
Dnotent des problmes de prcision dans
les calculs arithmtiques
range_error
A comparer l'exception de logique de
programme out_of_range, range_error
stipule plus une erreur interne au calcul
d'un argument qu'une erreur lie au
programmeur.
Exceptions issues de logic_error
length_error
A rapprocher de bad_alloc, cette
exception indique une tentative de
cration d'un objet de trop grande taille
out_of_range
Typiquement un accs en dehors des limites
d'index d'un tableau
domain_error invalid_argument
Trs semblables, ces exceptions traduisent
le passage d'un argument de type ou de
domaine inattendu.
Tableau 2.3 Spcificits des diffrentes exceptions de la STL

II-D-3 - Exemple d'utilisation des exceptions de la STL


L'exemple suivant montre l'utilisation de certaines des exceptions de la STL. Les commentaires sont placs dans
le code.

Programme 2.8 exemple complet d'utilisation des exceptions de la STL


#include <stdexcept>
#include
#include
#include
#include

<iostream>
<string>
<new>
<typeinfo>

using namespace std;


class Rationnel
{
protected:
int num;
int den;
public:
explicit Rationnel (int n=0, int d=1) : num(n), den(d) {}
void setNum(int n)

- 17 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Programme 2.8 exemple complet d'utilisation des exceptions de la STL


{

};

num=n;
}
void setDen(int d) throw (std::invalid_argument)
{
if (d == 0)
throw std::invalid_argument("Rationnel : passage de denominateur nul");
den=d;
}
double asDouble () throw (std::range_error)
{
if (den == 0)
throw std::range_error("Rationnel : division par 0");
return static_cast<double>(num)/den;
}

int main(int, char**)


{
const unsigned long exagerementGrand=10000000;
int
nouveauDen;
Rationnel
r1;
Rationnel
*poolRationnel;
try
{

Rationnel r2(2,0);
cout << r2.asDouble();

}
catch (std::range_error &e)
{
cerr << "Exception range_error levee : " << e.what() << endl;
}
catch (std::exception &e)
{
cerr << "Exception stl levee : " << e.what() << endl;
}
catch (...)
{
cerr << "Exception inconnue levee : abandon du programme" << endl;
exit(1);
}
do
{

cout << "Saisissez un nouveau denominateur" << endl << flush;


cin >> nouveauDen;
try
{
r1.setDen(nouveauDen);
}
catch (std::invalid_argument)
{
cerr << "Le denominateur ne doit pas etre nul, recommencez !" <<
endl;
continue;
}
break;
while (1);

try
{

poolRationnel = new Rationnel[exagerementGrand*exagerementGrand];


}
catch (std::bad_alloc &e)
{

- 18 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Programme 2.8 exemple complet d'utilisation des exceptions de la STL


cerr << "Vous avez demande trop de memoire !" << endl;
poolRationnel=0;

}
catch (...)
{
cerr << "Erreur inconnue !" << endl;
poolRationnel = 0;
}
delete [] poolRationnel;

return 0;

Figure 2.3 Sortie cran du programme prcdent

Commentons quelque peu les rsultats de ce programme :


1
2
3

La cration d'un Rationnel avec dnominateur nul lve une exception de type range_error : tout ce qu'il y a
de plus normal ! Vous noterez dans le code que nous sommes alls du gestionnaire le plus restrictif au plus
gnral.
Nous utilisons ici une exception l'intrieur d'une boucle. Tant que l'exception est leve, on ne peut pas sortir
de la boucle. C'est un systme de programmation assez gnral.
L'exception bad_alloc sanctionne un new qui ne s'est pas termin correctement.

Vous allez me dire il est toujours possible de vrifier si le pointeur demand n'est pas nul, il n'tait pas ncessaire
d'utiliser un mcanisme aussi lourd qu'une exception pour cela . Exact. Cependant, combien d'entre vous le font
systmatiquement ? D'accord, les exceptions ralentissent un programme et sont lourdes utiliser, toutefois, elles ne
peuvent tre ignores et permettent parfois de garantir le fonctionnement normal d'un programme.

II-D-4 - Aux utilisateurs de C++ Builder


Inprise propose aux utilisateurs de C++ Builder sa propre bibliothque d'exceptions au sein de la VCL (Visual
Components Library) dont la philosophie est totalement diffrentes : les exceptions de la STL sont d'abord destines
tre leves par l'utilisateur, celles de la VCL sont utilises par les composants pour signaler les erreurs l'utilisateur.
Notons galement que les arborescences des exceptions sont totalement diffrentes.
En effet, celle de la VCL rajoute des exceptions trs gnrales tout ce qui est ax
sur la programmation vnementielle. Essayer d'utiliser conjointement les deux types
d'exception n'est pas exclu mais peut s'avrer franchement dlicat, il faut, par exemple,
retenir que l'accs en dehors des bornes d'un vecteur de la STL gnre l'exception
std::out_of_range alors que l'accs en dehors des bornes d'un vecteur de la VCL (tel
que, par exemple, celui des lments d'une bote de liste) se traduit par une exceptions
ErangeError et qu'il sera souvent dlicat d'tablir un gestionnaire commun.

- 19 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Un autre point diffrenciant les exceptions VCL et STL rside dans le type des chanes de caractres impliques.
En effet, dans la STL, c'est, bien entendu, le type std::string qui est utilis alors que la VCL privilgie le type natif
de Windows : AnsiString.

II-E - Le Support de la RTTI


Avant toute chose prcisons tout de suite que les comits de normalisation n'ont pas encore dcid si le RTTI faisait
partie du langage C++ lui mme ou bien de sa librairie standard.
Sans vouloir entrer dans cette polmique - de faible intrt - je me contenterai de prsenter ici le RTTI sans me
soucier de savoir si c'est un composant de librairie ou bien un lment du langage.

II-E-1 - Qu'est ce que le RTTI


RTTI signifie littralement Run Time Type Information soit en Franais : Informations de Type disponibles
l'Excution. Ceci peut sembler incongru dans un langage orient objet dont le but est prcisment de se dlester sur
les fonctions virtuelles des problmes lis aux diffrents types des objets recenss dans un programme. D'ailleurs
Coplien crivait : il est absolument impensable que les programmeurs puissent savoir au cours de l'excution
quels types d'objets ils ont affaire .
Aussi, les informations de type ne seront utilises qu' des fins de diagnostic ou pour viter des erreurs de logique
dans les programmes. En outre, ces informations vont permettre d'utiliser en toute scurit l'une des fonctionnalits
les plus dcries de la programmation oriente objet : les promotions de pointeurs sur des objets galement appeles
downcast en permettant de vrifier que l'opration que l'on va effectuer est bien lgitime.

II-E-2 - La classe type_info et l'oprateur typeid


Le support du RTTI est indissociable de la classe type_info, qui, comme son nom le suggre est ddie l'exploitation
des informations de type contenues dans les classes. L'utilisation de cette classe ncessite l'inclusion de typeinfo.
La classe type_info possde la particularit de ne pas possder de constructeur public. En effet, il existe une et une
seule instance de type_info pour chaque classe prsente dans un excutable. Ces instances sont gnres lors du
lancement de l'excutable, et le seul moyen d'obtenir une rfrence (et encore constante !) passe par l'utilisation de
l'oprateur typeid. Celui-ci admet deux syntaxes :
const type_info &typeid( expression )
const type_info &typeid( nom-type )

Dans le premier cas, on obtient des informations sur le type d'une expression, par exemple, une variable, une
constante ou, plus gnralement, toute expression dote d'un type.
Dans le second cas, on demande une information de type en passant typeid le nom du type. Ceci est destin
tablir des comparaisons entre le type d'une expression et une srie de rfrences.
Les mthodes les plus utiles de la classe type_info sont les suivantes :
operator== bizarrement cod comme une mthode, cet oprateur teste l'galit entre deux informations de type.
operator!= galement (et toujours aussi bizarrement -) cod comme une fonction membre, cet oprateur teste
la diffrence entre deux informations de type. Il parat redondant d'avec le prcdent et n'est pas gnr
automatiquement comme !operator==.

- 20 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

before est assurment l'oprateur (boolen) le plus intressant, en effet a.before(b) renvoie true si et seulement si
a correspond une super classe de b. C'est prcisment cette information qui est utilise par dynamic_cast pour
vrifier l'intgrit d'un downcast.
name renvoie une chane de caractres (de type char * -) indiquant en clair le nom de la classe associe au type_info.

II-E-3 - Exemple d'utilisation du RTTI


L'exemple suivant cre des classes, les instancie et teste l'oprateur == ainsi que les mthode before et name du
RTTI.
Important ! A l'heure o ces lignes sont tapes, name fonctionne correctement avec C++ Builder et before avec g++
mais pas l'inverse ! Esprons que tout ceci soit bien vite rectifi ! Le rsultat cran fourni est donc une compilation
idyllique des rsultats fournis dans ces deux environnements.

Programme 2.9 utilisation des type_info et de typeid


#include <iostream>
#include <typeinfo>
class A
{
public:
A() {}; // ce constructeur par dfaut est ncessaire
// sinon l'on obtient une erreur uninitialized constant
// pour la variable aa dans main
};
class B {};
class C : public A {};
class D : public A {};
class E : public C {};
int main(int, char **)
{
A
a;
const A aa;
A
*pa = new A;
B
b;
C
c;
D
d;
E
e;
cout
<<
cout
<<
cout
<<
cout
<<

<< "Affichage du nom d'une classe


typeid(A).name() << endl;
<< "Affichage du nom de la classe
typeid(a).name() << endl;
<< "Affichage du nom de la classe
typeid(pa).name() << endl;
<< "Affichage du nom de la classe
typeid(*pa).name() << endl;

"
d'un objet "
d'un pointeur "
d'une variable via pointeur "

cout << "Arithmetique sur les types " << endl;


cout
<<
cout
<<

<< "Variable et *pointeur de meme type "


(typeid(a) == typeid(*pa)) << endl;
<< "Variable et const Variable de meme type "
(typeid(a) == typeid(aa)) << endl;

cout
<<
cout
cout
<<
cout

<< "Variables de types differents "


(typeid(a) == typeid(b)) << endl;
<< "Essai de before " << endl;
<< "Variables de classes differentes "
typeid(a).before(typeid(b)) << endl;
<< "Classe meme et classe Fille "

- 21 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Programme 2.9 utilisation des type_info et de typeid

<< typeid(a).before(typeid(c)) << endl;


cout << "Classe grand meme et classe petite fille "
<< typeid(a).before(typeid(e)) << endl;
cout << "Classe tante et classe niece "
<< typeid(d).before(typeid(e)) << endl;

return 0;

Figure 2.4 Rsultat cran du programme prcdent

Quelques commentaires :

Il n'y a pas grand chose dire sur le rsultat de name sinon que, lorsque cela fonctionne, c'est assez gnial !
Les rsultats fournis par == sont conformes ce que l'on pourrait attendre une surprise prs : const A et A
sont ici considrs comme des types identiques.
La sortie cran de before est la plus intressante et donne elle aussi des rsultats sans surprise :

Bien entendu la comparaison de deux classes sans parent renvoie faux

Une classe grand mre est bien annonce comme anctre de sa petite fille

Une classe tante n'est pas reconnue comme anctre de sa nice

- 22 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

III - Les classes conteneur de la STL


De toutes les fonctionnalits prsentes dans la STL, la plus connue (et celle qui a assur sa popularit) repose sur
les classes conteneur. Celles ci fournissent des implmentations de grande qualit pour les structures de donnes
les plus courantes ainsi que des algorithmes gnriques permettant de travailler avec elles.

III-A - Philosophie gnrale


En guise de prambule, il est trs important de noter que la STL est issue de concepts non orients objet. Pour tre
prcis, ces prcurseurs ont vus le jour en Ada 83. C'est pourquoi sa structure peut paratre hrtique des gens
pntrs de culture Objet.
En effet, l'architecture de la STL prne une sparation trs forte entre la notion de conteneur et celle d'algorithme.
A l'oppos des concepts habituellement retenus, les algorithmes classiques (tri, change de donnes, recopie de
squences) ne sont pas des mthodes des conteneurs mais des fonctions externes ou des objets foncteurs qui
interagissent avec les conteneurs via les itrateurs, ces derniers n'tant ni plus ni moins que des objets permettant
de baliser et / ou de parcourir des conteneurs.

III-B - Prsentation des conteneurs


D'aprs la littrature propose sur la STL, on peut ranger les conteneurs en trois catgories :
Les squences lmentaires (quelquefois appels stockages lmentaires)
Les utilisations spcialises des squences lmentaires (parfois et improprement appeles type abstrait de
donnes)
Les conteneurs associatifs bass sur la notion de paire (clef, valeur)
Revenons brivement sur chacun d'eux.

III-B-1 - Prsentation des squences lmentaires


Les squences lmentaires sont les structures de donnes lmentaires retenues par le comit de standardisation
de la STL pour servir de base des structures de donnes plus labores. Remarquons toutefois qu'elles sont
nanmoins disponibles l'utilisateur final !
On y retrouve : les vecteurs, les listes, les listes accs prfrentiel premier dernier ou DQ (deques en rosbif.

III-B-1-a - Les vecteurs


Les vecteurs de la STL sont tout fait semblables aux tableaux que l'on a l'habitude de manipuler en C++. Ils sont
nanmoins encapsuls dans des classes pour leur fournir des capacits supplmentaires, en particulier, la croissance
dynamique. Leurs principales caractristiques sont les suivantes :

Accs index aux lments en O(1)


Ajout ou suppression d'un lment la fin du vecteur sans redimensionnement en O(1)
Ajout ou suppression d'un lment la fin du vecteur avec redimensionnement en O(n)
Ajout ou suppression d'un lment au milieu du vecteur en O(n) o n est la taille du vecteur
Ajout ou suppression d'un lment la fin du vecteur en O(1) amorti

- 23 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Il convient de mettre un bmol concernant l'ajout d'un lment la fin d'un vecteur. En effet, les vecteurs sont
croissance dynamique. Autrement dit, si vous dcidez d'ajouter un lment dans un vecteur dj plein l'aide de la
mthode push_back (dtaille plus bas), celui-ci sera agrandi, ce qui ncessite trois oprations :
1
2
3

Allocation d'un nouveau vecteur


Recopie des lments depuis l'ancien vecteur vers le nouveau
Suppression de l'ancien vecteur

Or, ces oprations peuvent tre coteuses, au pire en O(n). Se pose galement la question du choix de la future taille.
Andrew Koenig nous explique que la technique la plus efficace consiste utiliser un redimensionnement exponentiel
i.e. chaque rallocation, la taille du vecteur est multiplie par un facteur (1 + a) o a est un nombre strictement
positif. Ainsi, plus le vecteur devient grand, plus il s'agrandira rapidement.
Cette stratgie a l'avantage de rendre les redimensionnement de moins en moins frquents au dtriment d'un
encombrement parfois exagr de la mmoire. Du fait de la frquence faible des redimensionnements, on peut
considrer que la complexit asymptotique (ou amortie) de l'opration d'ajout d'un lment en bout de tableau est
en O(1).
Notons immdiatement que l'accs, que ce soit en lecture ou en criture, d'un lment
en dehors des bornes actuelles d'un tableau se traduit immdiatement par la leve d'une
exception out_of_range (voir la Figure 2.2 pour une vue d'ensemble des exceptions de
la STL).

III-B-1-b - Les listes


Elles modlisent le type liste chane habituel. Contrairement aux vecteurs, elle ne possdent pas d'oprateur
d'indexation mais permettent d'ajouter ou de supprimer un lment n'importe quelle position en O(1).
Bien qu'il n'y ait jamais de place morte dans une liste mais, du fait de la structure de chane, l'occupation en mmoire
d'une liste est le plus souvent suprieure celle d'un vecteur pour le mme nombre d'lments stocks.

III-B-1-c - Les DQ
Les DQ sont la squence lmentaire la plus dlicate cerner car Intermdiaire entre une liste et un vecteur.

Elle est trs efficace ds lors qu'il s'agit d'ajouter ou de retirer une valeur l'une de ses extrmits.
Elle possde un oprateur d'indexation de complexit o(log(n)) amortie
Les insertions en milieu de squence sont plus rapides que sur un vecteur sans pour autant atteindre le
niveau de performances des listes

III-B-2 - Les oprations disponibles sur l'ensemble des squences


Les mthodes suivants sont disponibles sur l'ensemble des conteneurs de base de la STL.

Gestion de la taille du conteneur


Renvoie le nombre d'lments prsents
dans le conteneur
size_type max_size () const;
Renvoie le nombre maximal d'lments que
peut receler un conteneur.
bool empty () const;
Renvoie true si le conteneur est vide
void resize (size_type,T c = T())
Redimensionne le conteneur. Si celui-ci
est raccourci, les lments terminaux sont
size_type size () const;

- 24 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

supprims sans autre forme de procs. En


revanche, si le conteneur est agrandi, de
nouveaux lments sont ajouts la fin
conformment au second paramtre
Accs aux lments
reference front (); const_reference front ()
Renvoie une rfrence sur le premier
const;
lment. Existe en version const et non
const
reference back (); Existe en version const et
non const
Insertion d'lments
void push_back (const T&);
Ajouter l'lment spcifi par rfrence au
bout de la collection. Appelle pour cela le
constructeur par recopie
void pop_back ();
Retire l'lment en fin de collection
iterator insert (iterator, const T& = T()); void Insre un lment (ventuellement
insert (iterator, size_type, const T& = T());
construit par le constructeur par dfaut)
l'emplacement spcifi par l'itrateur pass
en premier argument La deuxime version
permet d'ajouter un facteur de rptition
Seule la liste garantit un fonctionnement
uniforme de ces mthodes en o(1)
template <class InputIterator> void insert
Insre la position position les lments
(iterator position, InputIterator debut,
contenus dans l'intervalle [debut fin[. Les
InputIterator fin);
itrateurs debut et fin doivent se trouver sur
la mme collection. Seule la liste garantit un
fonctionnement uniforme de ces mthodes
en o(1)
Suppression d'lments
void erase (iterator);
Supprime l'lment plac sous l'itrateur
void erase (iterator debut, iterator fin);
Supprime les lments placs dans
l'intervalle [debut fin[
Echange d'lments
void swap (squence<T>&);
O squence est remplacer par vector, list
ou deque ! Echange les lments de this
avec ceux du conteneur pass en paramtre
Le codage mthode ne fonctionne que
sur des squences de type rigoureusement
identique. Pour changer les lments de
squences diffrentes, il faut recourir la
version fonction oriente itrateurs
Tableau 3.1 Les oprations disponibles sur toutes les squences lmentaires

- 25 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

III-B-3 - Oprations spcifiques


III-B-3-a - Oprations spcifiques sur les vecteurs
Gestion de la capacit
Renvoie la capacit c'est dire le nombre
d'lments que peut contenir le vecteur
avant redimensionnement
void reserve (size_type);
Ajoute de la capacit un vecteur
Accs index aux lments
Reference operator[] (size_type);
Oprateur d'indexation, existe en version
const_reference operator[] (size_type) const; const et non const. Renvoyer une rfrence
Reference at (size_type n); const_reference permet d'utiliser le retour en tant que lvalue
at (size_type n) const;
pour la version non const. La mthode at
effectue exactement la mme opration que
l'oprateur crochets
size_type capacity () const;

Tableau 3.2 Mthodes spcifiques vector


En outre, il faut savoir que si vous crez un vecteur avec une dimension initiale suprieure 0, le constructeur par
dfaut du type lment est appel pour crer un premier lment et le tableau est ensuite rempli par des appels au
constructeur de recopie.
Afin de bien comprendre les mcanismes de cration d'objets, que ce soit par le constructeur par dfaut ou par appel
au constructeur de recopie, nous utilisons la classe suivante qui encapsule les entiers :

Programme 3.1 La classe Entier


// Fichier d'entete Entier.hxx
#ifndef __Entier__
#define __Entier__
class Entier
{
private:
static unsigned NbEntiers_;
static unsigned NbRecopies_;
int
val_;
public:
explicit Entier(int valeur=0) : val_(valeur)
{
NbEntiers_++;
}
Entier (const Entier &a)
{
val_=a.val_;
NbRecopies_++;
}
int val(void) const
{
return val_;
}
static int NbEntiers(void)
{
return NbEntiers_;
}

- 26 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Programme 3.1 La classe Entier


static int NbRecopies(void)
{
return NbRecopies_;
}
};
class ostream;
ostream &operator<<(ostream &a,const Entier &b);
bool operator==(const Entier &a, const Entier &b);
bool operator<(const Entier &a, const Entier &b);
#endif
// fichier Entier.cpp
#include "Entier.hxx"
#include <iostream>
ostream &operator<<(ostream &a,const Entier &b)
{
a << b.val();
return a;
}
bool operator<(const Entier &a, const Entier &b)
{
return a.val() < b.val();
}
bool operator==(const Entier &a, const Entier &b)
{
return a.val() == b.val();
}
unsigned int Entier::NbEntiers_=0;
unsigned int Entier::NbRecopies_=0;

Le point intressant rside dans l'utilisation des attributs de classe NbEntiers_ et NbRecopies_ comptant
respectivement le nombre d'appels au constructeur de cration et le nombre d'appels au constructeur de recopie.
Nous pourrons donc suivre la trace ces oprations.
En outre, cela nous permet de voir les pr requis ncessaires l'utilisation d'une classe par la STL :

Constructeur par dfaut


Constructeur par recopie. Ici, le constructeur par recopie gnr automatiquement tait suffisant, nous ne
l'avons construit nous mme que pour utiliser le comptage des appels
Oprateur d'affectation, ici celui fourni automatiquement par le compilateur
Oprateur de sortie sur flux <<
Oprateur de comparaisons < et ==, les autres tant automatiquementconstruits par template.
Notez galement que le constructeur est dclar explicit pour viter toute conversion
implicite avec un entier. Ici cela n'tait toutefois pas dangereux. De mme nous aurions
trs bien pu dfinir un oprateur de conversion implicite vers les entiers, sous la forme :
operator int (void)
{
return val_;
}

Toutefois, il me parat prfrable de laisser le soin l'utilisateur de raliser les conversions de faon explicite lorsqu'il
en a lui mme besoin !
- 27 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Il est important de noter que le redimensionnement du tableau - que ce soit par un appel direct reserve o
automatiquement lorsque l'on arrive en limite de capacit n'implique pas de cration d'objet mais uniquement de la
rservation de mmoire. En outre, ces oprations n'affectent que la capacit et en aucun cas la taille.
En revanche, resize, en mode accroissement, conjugue rservation de mmoire et cration d'objets comme en
tmoigne les augmentations de taille (size)

Programme 3.2 Manipulations sur la taille des vecteurs


#include <vector>
#include <iostream>
#include "Entier.hxx
// Permet d'afficher les caracs du vecteur
// et le nombre d'entiers
template <class T>
void affichage(const T &a)
{
static int numeroLigne=1;
cout << '(' << numeroLigne++ << ") Capacite " << a.capacity();
cout << " Taille " << a.size();
cout << " Nb entiers " << Entier::NbEntiers() << endl << flush;
}
int main(int, char**)
{
typedef std::vector<Entier> VecInt;
VecInt v1;
// Creation d'un vecteur vide
affichage(v1);
// (1)
v1.push_back(Entier(1)); // insertion d'un element
affichage(v1);
// (2)
v1.reserve(100);
// la capacite est portee a 100
affichage(v1);
// (3)
v1.resize(200);
// capacite et taille portees a 200
affichage(v1);
// (4)
VecInt v2; // Nouveau vecteur vide
for (int i=0;i<20;i++) // Remplissage avec redimensionnements
{
v2.push_back(Entier(i));
affichage(v2); // (5 -> 24)
}
for (int i=0;i<20;i++) // Affichage par indexation (25)
cout << v2[i] << " ";
cout << endl;
// Affichage avec parcours d'iterateur (26)
VecInt::iterator courant=v2.begin();
while (courant != v2.end())
{
cout << *courant << " ";
++ courant; // Je me souviens du cours de C++ avance
// utiliser si possible l'operateur prefixe !
}
cout << endl;
// Affichage avec iterateur de flux (27)
copy(v2.begin(),
v2.end(),
ostream_iterator<Entier>(cout," "));
cout << endl;
}

return 0;

- 28 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Le rsultat d'excution est le suivant :

Figure 3.1 Rsultat du programme d'essai sur vector


Commentons une par une ces quelques lignes de sortie. Les commentaires du code font rfrence aux lignes de
sortie.
1
2
3

Le tableau est vide, sa capacit et sa taille sont nulles : prvisible


On ajoute un lment, la capacit et la taille passent 1, et l'on a allou un entier : toujours prvisible.
Le nombre de recopies augmente d'une unit : ceci signifie que l'opration de recopie de l'ancien vecteur lors
d'un redimensionnement se fait par appel l'oprateur de construction par recopie.
La capacit passe 100 alors que la taille ne bouge pas, c'est typique du fonctionnement de reserve. Le fait
que le nombre de crations d'entier n'ait pas boug atteste du fait que reserve se contente d'allouer de la
mmoire sans crer un seul objet. Le nombre de recopies augmente d'une unit pour la raison voque au
point prcdent.
La capacit passe 200 ainsi que la taille, c'est le rle de resize : amener la taille la valeur spcifie en
augmentant si ncessaire la capacit. En revanche, le point intressant concerne le nombre d'entiers : un
seul nouvel entier a t cr par le constructeur par dfaut, les autres ont t gnrs par recopie comme
l'atteste la brusque monte du nombre de recopies !
Les lignes 5 24 permettent de bien voir le mcanisme de redimensionnement partir d'un tableau vide.
Dans ce cas (gcc), le redimensionnement est double chaque tape. Eussions nous utilis la Rogue Wave
que la capacit serait passe de 0 256 avant d'tre double chaque tape.
Le nombre de recopies atteste que ce mcanisme est utilis :

D'une part lors des redimensionnements (voir point 2)

Par chaque opration push_back : l'lment pass push_back (par rfrence constante pour viter
une recopie de plus) est recopi son emplacement dans le vecteur.
Finalement, nous procdons l'affichage des valeurs contenues dans le vecteur par trois mthodes
diffrentes :

Ligne 25 : accs avec l'oprateur d'indexation (mthode classique)

Ligne 26 : parcours avec itrateurs

Ligne 27 : utilisation d'un itrateur de flux

Vous remarquerez que nous obtenons trois fois de suite la mme solution, ce qui est trs rassurant !

III-B-3-b - Oprations spcifiques sur les listes


Les oprations spcifiques sur les listes concernent essentiellement l'insertion et la suppression en tte de liste, le
transfert d'lments entre listes avec une mthode spcifique (splice), ainsi que le rordonnement de la collection.

- 29 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Insertions et retraits en ttes de liste


void push_front (const T& x);
Insre un lment en tte de liste
void pop_front ();
Retire l'lment en tte de liste
Transfert d'lments entre listes
Permettez moi un petit blah pipo (merci Pookie -) avant d'entrer dans le lard (oups, on dit
le vif) du sujet Toutes ces oprations sont ralises en O(1) grce la structure chane
spcifique de la liste. Elles sont donc prfrer aux algorithmes gnriques pour des
raisons de performance. En outre, toutes les insertions se font avant la position indique
par un itrateur nomm position. En effet, cela permet d'ajouter la fin d'une squence en
spcifiant end() pour position.
void splice (iterator position, list<T>& x);
la fin de cette opration x est vide.
void splice (iterator position, list<T>& x,
Insre dans la liste courante et avant
iterator i);
position, l'lment de x point par i
void splice (iterator position, list<T>& x,
Insre dans la liste courante et avant
iterator debut, iterator fin);
position, l'ensemble des lments de x
compris dans l'intervalle [debut fin[
Suppressions d'lments
void remove (const T& value);
Supprime tous les lments de valeur value.
L'ordre des lments non supprims n'est
pas modifi (ouf -)
template <class Predicate> void remove_if
Supprime tous les lments de la liste
(Predicate pred);
vrifiant le prdicat pred. L'ordre des
lments non supprims n'est pas modifi
void unique ();
Compresse une seule occurrence les
valeurs successives identiques
template <class BinaryPredicate> void
Compresse une seule occurrence les
unique (BinaryPredicate pred);
valeurs successives qui vrifient le prdicat
binaire pred
Concatnation de listes
void merge (list<T>& x);
Trie la liste courante puis lui ajoute les
lments de x en les intercalant. Ces
oprations sont effectues respectivement
l'oprateur <. Si deux lments, l'un de this
et l'un de x ont mme valeur de clef, alors
l'lment de this prcde l'lment de x dans
le rsultat.
template <class Compare> void merge
Trie la liste courante selon l'ordre indiqu
(list<T>& x, Compare comp);
par l'objet foncteur comp puis lui ajoute les
lments de x en les intercalant toujours
en fonction de l'objet foncteur comp. Mme
remarque que prcdemment.
Tris
void sort ();
Trie les lments selon l'oprateur < Le tri
est stable, c'est dire que l'ordre relatif des
lments de mme clef n'est pas modifi
template <class Compare> void sort
Trie les lments selon l'ordre indiqu par
(Compare comp);
l'objet foncteur comp. Le tri est stable
void reverse();
Renverse l'ordre des lments dans la liste
Tableau 3.3 Oprations spficiques list
Suit un petit exemple montrant l'utilisation des lments spcifiques au type list.

Programme 3.3 Dmonstration du type list

- 30 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Programme 3.3 Dmonstration du type list


#include <list>
#include <iostream>
#include <algo.h>

#include "Entier.hxx"
#include "Genera.hxx"
// Predicat fonction
bool estPair(const Entier &a)
{
return ((a.val() % 2) == 0);
}
// Predicat foncteur
class EstImpair
{
public:
bool operator()(const Entier &a)
{
return ((a.val() % 2) != 0);
}
};
int main(int, char**)
{
typedef std::list<Entier> ListEnt;
typedef ListEnt::iterator ListEntIt;
ListEnt l1;
ostream_iterator<Entier> sortie(cout, " ");
cout << "Generation aleatoire d'une liste de 10 entiers" << endl;
l1.resize(10);
generate(l1.begin(), l1.end(), GenAlea());
cout << "Affichage de l'ordre initial" << endl;
copy(l1.begin(),l1.end(),sortie);
cout << endl;
cout << "Apres tri" << endl;
l1.sort();
copy(l1.begin(),l1.end(),sortie);
cout << endl;
cout << "Apres renversement" << endl;
l1.reverse();
copy(l1.begin(),l1.end(),sortie);
cout << endl;
cout << "Generation lineaire des 10 premiers entiers" << endl;
generate(l1.begin(), l1.end(), GenLin());
copy(l1.begin(),l1.end(),sortie);
cout << endl;
cout << "Obtention de deux iterateurs sur le 3 et sur le 8" << endl;
cout << "Construction d'une seconde liste puis splice " << endl;
// notez ici que nous sommes obliges d'utiliser Entier(3) pour chercher le 3
// cette conversion aurait ete implicite si le constructeur d'entier
// n'avait pas ete marque explicit
// je prefere toutefois controler ce que fait mon programme et faire l'effort
// de l'appel de constructeur moi meme
ListEntIt gauche=find(l1.begin(),l1.end(),Entier(3));
ListEntIt droite=find(l1.begin(),l1.end(),Entier(8));
ListEnt l2;
l2.splice(l2.begin(),l1,gauche,++droite);
cout << "Liste initiale : ";
copy(l1.begin(),l1.end(),sortie);
- 31 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Programme 3.3 Dmonstration du type list


cout << endl;

cout << "Seconde liste : ";


copy(l2.begin(),l2.end(),sortie);
cout << endl;
cout << "Creation d'une liste des elements pairs par suppression des impairs";
cout << endl;
l1.resize(10);
generate(l1.begin(),l1.end(),GenLin());
l1.remove_if(EstImpair());
copy(l1.begin(),l1.end(),sortie);
cout << endl;
cout << "Creation d'une liste des elements impairs par suppression des pairs";
cout << endl;
l2.resize(10);
generate(l2.begin(),l2.end(),GenLin());
l2.remove_if(estPair);
copy(l2.begin(),l2.end(),sortie);
cout << endl;
cout << "Apres Merge" << endl;
l1.merge(l2);
copy(l1.begin(),l1.end(),sortie);
cout << endl;
}

return 0;

Figure 3.2 Sortie cran de la dmonstration de list

Quelques commentaires s'imposent aussi bien sur le programme que sur son rsultat.

Tout d'abord, nous utilisons l'algorithme generate pour gnrer (on s'en doutait un peu -) des valeurs dans les
listes.
Les emplacements doivent dj tre rservs ! generate n'ajoutera pas d'lments dans votre liste mais crase
les valeurs dj prsentes. D'ailleurs, generate utilise une paire d'itrateurs pour spcifier les lments remplir.
L'algorithme generate utilise un objet foncteur dont l'oprateur fonction (operator ()) ne doit pas prendre de
paramtre et renvoyer un objet compatible avec le type prsent dans la liste. Ici nous utilisons deux classes
d'objets foncteurs : GenAlea et GenLin. Le programme suivant fournit leur code :

Programme 3.4 Les classes de gnrateurs GenAlea et GenLin


#ifndef __Genera_hxx__
#define __Genera_hxx__

- 32 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Programme 3.4 Les classes de gnrateurs GenAlea et GenLin


#include "Entier.hxx"

class GenAlea
{
private:
static const unsigned long m=259200UL;
static const unsigned long a=5141UL;
static const unsigned long c=73141UL;
unsigned long x;
public:
explicit GenAlea(unsigned long t=0) : x(t) {};
Entier operator()(void)
{
x=(x*a+c)%m;
return Entier(x);
}
};
class GenLin
{
private:
int prochain;
public:
explicit GenLin(int leProchain=0) : prochain(leProchain) {};
Entier operator()(void)
{
return Entier(prochain++);
}
};
#endif

Les deux classes proposes sont les suivantes :


GenAlea est un gnrateur de nombres pseudo alatoires simpliste
GenLin cre des entiers dans l'ordre croissant partir de la valeur passe son constructeur et par dfaut gale 0.

Autre point notable, l'utilisation de splice. Ici, nous utilisons l'algorithme find qui permet de recherche une
valeur parmi les lments contenus dansun intervalle spcifi par une paire d'itrateurs.
Nous dsirons transfrer les lments de 3 8 vers une autre liste. Nous recherchons donc ces deux lments
avec find de manire obtenir des itrateurs respectivement nomms gauche et droite. Hors si nous avions
pass la commande :
l2.splice(l2.begin(),l1,gauche,droite);

Nous n'aurions transfr que les lments [3, prdcesseur de 8] vers l2 car le second itrateur est une borne non
incluse.
Afin de transfrer jusqu' droite inclus, nous utilisons l'oprateur ++ sur l'itrateur droite, soit :
l2.splice(l2.begin(),l1,gauche,++droite);

La mthode remove_if permet de supprimer des lments d'une liste en fonction d'un critre pass sous
forme de prdicat. Celui ci peut prendre deux formes :

Une fonction bool

Un objet foncteur dont l'oprateur fonction (operator ()) renvoie bool

- 33 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Notre exemple illustre ces deux possibilits en fournissant une fonction de test de parit et un foncteur qui test
l'inverse !

Finalement, nous utilisons merge pour rassembler deux listes

III-B-3-c - Oprations spcifiques sur les DQ


Les oprations spcifiques aux DQ concernent l'insertion et la suppression en tte de conteneur. Oprations qui
sont ici particulirement optimises ! On note galement la prsence d'un oprateur d'accs index relativement
performant.

Accs index aux lments


reference operator[] (size_type);
Oprateur d'indexation, existe en version
const_reference operator[] (size_type) const; const et non const. Renvoyer une rfrence
reference at (size_type n); const_reference permet d'utiliser le retour en tant que lvalue
at (size_type n) const;
pour la version non const. La mthode at
effectue exactement la mme opration que
l'oprateur crochets Ces oprations sont
garanties de complexit amortie o(log(n))
Insertions et retraits en tte de DQ
Ces oprations sont typiques de la DQ et donc particulirement performantes
void push_front (const T& x);
Insre un lment en tte de liste
void pop_front ();
Retire l'lment en tte de liste
Tableau 3.4 Oprations spcifiques au type deque
L'utilisation du type deque ne prsente aucune difficult, un exemple ne s'impose donc pas. En fait, vous utiliserez
deque lorsque vous avez besoin la fois de l'indexation et de l'accs aux lments extrmes d'une collection.

III-B-4 - Itrateurs et squences lmentaires


Les squences lmentaires sont associes des itrateurs bidirectionnels. On peut galement toutes les doter
d'itrateurs d'insertion avec une mention spciale pour la liste.
En outre, vector et deque tant des conteneurs indexs, ils fournissent des itrateurs accs alatoire

III-B-5 - Les utilisations spcialises des squences lmentaires


Les utilisations spcialises des squences lmentaires modlisent trois structures de donnes classiques : les
piles, les files et les files priorit. Il faut bien noter que ce sont des classes qui adaptent une squence lmentaire
une structure de donne en lui fournissant une nouvelle interface. Lorsque vous aurez besoin d'une de ces classes,
vous devrez lui indiquer si elle doit tre base sur un vecteur, une liste ou une DQ.

III-B-5-a - Aspects gnraux


A l'instar des autres conteneurs de la STL, les mthodes size et empty renvoient respectivement un entier indiquant
le nombre d'lments prsents dans le conteneur et un boolen signalant si le conteneur est vide.
En outre, aucun de ces trois types ne supporte les itrateurs. Aussi, les algorithmes gnraux (que nous verrons
dans un prochain chapitres) seront ils gnralement inutilisables sur ce genre de conteneurs ce qui n'est pas sans
poser certains problmes de compatibilit.

- 34 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Les types files et piles ne posant pas de problmes particuliers, nous ne donnerons pas ici d'exemple particulier.
L'exemple final sur les graphes donnera deux utilisations sur les parcours de graphe en profondeur d'abord ou en
largeur d'abord.

III-B-5-b - Les files (queues)


Les files sont associes au modle d'accs premier arriv, premier trait, l'image, par exemple, d'une file d'attente
un guichet. Les oprations offertes sont trs limites car elles permettent d'ajouter un lment la fin, consulter
l'lment prsent chaque bout, retirer l'lment en tte de file.

Deux particularits notables sur les files :

elles ne possdent pas d'autre constructeur que celui par dfaut (sans argument)
afin de fonctionner correctement, les oprations == et <= sont requises sur letype T des lments que l'on
souhaite loger dans la file.

Les files effectuant des accs frquents aux deux extrmits de la structure de donne sous-jacent ne doivent pas
tre construites sur un vecteur (le retrait d'un lment en tte serait trop lent) mais plutt sur une liste ou une DQ.
Toutefois, il est conseill d'utiliser une DQ qui offre de meilleurs temps de rponse pour les oprations d'ajout et
de suppression aux deux extrmits. D'ailleurs, si votre compilateur accepte les template avec valeur par dfaut, la
construction se fait automatiquement sur une DQ.
La dclaration d'une file obit au prototype suivant :
template <class T, class Container = deque<T> >
class queue
{ // etc

L'on y retrouve le type T des lments stocks dans la file ainsi que le type de la structure de donnes de base sousjacente initialise par dfaut une DQ sur T. Les oprations suivantes sont disponibles sur une file :

value_type& front (); const value_type& front Accde l'lment situ en tte de file sans
() const;
le retirer, existe en version const et non
const
value_type& back (); const value_type& back Accs l'lment situ la fin de la file
() const;
sans le retirer, existe en version const et non
const
void pop ();
Retire l'lment situ en tte de file
void push (const value_type& x);
Ajoute un lment la fin de la file
Tableau 3.5 Oprations disponibles sur une file

III-B-5-c - Les piles (stack)


Les piles sont associes au modle d'accs aux donnes dernier arriv premier sorti. En d'autres termes, le premier
lment tre entr dans la pile sera le premier utilis. Le modle tire son nom de l'analogie avec une pile d'assiette
o l'on accde toujours au mme lment : celui du dessus que ce soit par empilage ou dpilage. Il est possible de
baser une pile sur tous les types de structures lmentaires.
On notera toutefois qu'utiliser une liste s'avre peu judicieux car l'on accde qu' l'lment final. Aussi on se limitera
aux vecteurs et aux DQ. Les gourous de la STL assurent qu'utiliser une DQ se rvle trs lgrement plus
performant (un fait que je n'ai pas pu tablir personnellement, les diffrences de temps tant trop faibles pour tre
significatives) et, d'ailleurs, si votre compilateur accepte les template avec valeur par dfaut, une DQ sera utilise
par dfaut.
- 35 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

A l'instar des files, les piles n'ont qu'un constructeur par dfaut, il n'est pas possible d'obtenir d'itrateurs sur les piles,
et le type des lments que vous souhaitez loger dans une pile doit supporter les oprations == et <=.
La dclaration d'une pile obit au prototype suivant :
template <class T, class Container = deque<T> >
class stack
{ // etc

L'on y retrouve le type T des lments stocks dans la pile ainsi que le type de la structure de donnes de base sousjacente initialise par dfaut une DQ sur T. Les oprations disponibles sur une pile sont les suivantes :

value_type& top (); const value_type& top () Accde l'lment au sommet de la pile
const;
sans le retirer, existe en version const et non
const
void pop ();
Retire l'lment au sommet de la pile
void push (const value_type& x);
Ajoute un lment au sommet de la pile
Tableau 3.6 Oprations disponibles sur les piles

III-B-5-d - Exemple sur les piles et les files


Le petit fragment de code suivant montre la diffrence de gestion des piles et des files.

Programme 3.5 Programme de test piles et files


#include
#include
#include
#include
#include

<deque>
<queue> // pour les files
<stack> // pour les piles
<iostream>
<algo.h>

#include "Entier.hxx"
#include "Genera.hxx"
int main(int, char**)
{
const int TAILLE=10;
Entier i;
GenAlea g;
stack<Entier,deque<Entier> > pile;
queue<Entier,deque<Entier> > file;
cout << "Ordre d'entree : ";
for (int j=0;j<TAILLE;j++)
{
i=g();
cout << i << " ";
pile.push(i);
file.push(i);
}
cout << endl;
cout << "Ordre de sortie pour la pile : ";
while (!pile.empty())
{
cout << pile.top() << " ";
pile.pop();
}
- 36 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Programme 3.5 Programme de test piles et files


cout << endl;

cout << "Ordre de sortie pour la file : ";


while (!file.empty())
{
cout << file.front() << " ";
file.pop();
}
cout << endl;
}

return 0;

Figure 3.3 Sortie cran du programme de test piles / files


Ce programme montre bien que les lments de la file ressortent dans leur ordre d'arrive alors qu'ils en ressortent
dans l'ordre inverse pour une pile. La section sur les graphes montrera une autre application des piles et des files.

III-B-5-e - Les files priorit


Les files priorit (ou tas) sont des collections ordonnes d'lments qui ne donnent accs qu' un seul lment : le
plus prioritaire. La priorit est dtermine en fonction d'un prdicat pass au constructeur de la structure.
Les utilisations des files priorit sont multiples. Citons par exemple l'ordonnancement des processus dans un
systme d'exploitation. L'algorithme du tri en tas peut tre divis en deux phases : construction d'un tas puis extraction
du meilleur lment tant que le tas n'est pas vide.
Les files priorit doivent tre bases sur une structure indexe - ce qui limine les listes d'entre de jeu ! Si
l'occupation mmoire n'est pas votre soucis majeur, vous aurez intrt choisir une DQ qui autorise des oprations
plus rapides. En outre, si votre compilateur autorise les valeurs par dfaut pour les template, votre file priorit sera
construite par dfaut sur une DQ.
Examinons d'un peu plus prs la dclaration du type priority_queue :
template <class T,
class Container = vector<T>,
class Compare = less<Container::value_type> >
class priority_queue
{ // etc

En plus du type des lments (T) et du type du conteneur de base (Container dont la valeur par dfaut est une DQ
base sur T) on remarque la prsence d'un troisime paramtre template nomm Compare : le type du prdicat
de comparaison.
Celui-ci prend comme valeur par dfaut la comparaison infrieure ce qui fait de la priority_queue par dfaut un tas
min !
Contrairement aux types file et pile, la classe priority_queue dispose de deux constructeurs :

Un constructeur par dfaut de prototype :

- 37 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

explicit priority_queue (const Compare& x = Compare());

Vous noterez que les concepteurs de la STL ont pris soin de dclarer ce constructeur un paramtre explicit afin
d'viter d'ventuelles conversion implicites errones depuis un prdicat vers un tas !
Le paramtre par dfaut de ce constructeur est un objet directement instanci partir de la classe comparateur.
Certains compilateurs ne supportent pas cette opration et exigent que vous construisiez vous mme cet objet.

Un constructeur permettant de construire un tas partir d'une squence d'lments en provenance d'un
conteneur et dlimite par une paire d'itrateurs :
template <class InputIterator>
priority_queue (InputIterator first,
InputIterator last,
const Compare& x = Compare());

Notez qu'il s'agit ici d'un membre template, il vous faudra vrifier la conformit de votre
compilateur avant d'utiliser une telle fonctionnalit.
Les oprations disponibles sur les files priorit sont les suivantes :

const value_type& top () const;


void pop()
void push (const value_type& x);

Accde l'lment le plus prioritaire.


Notez qu'il n'existe qu'un accs const
Retire l'lment le plus prioritaire
Ajoute un lment dans la structure.
Celui ci est stock conformment sa
priorit

Tableau 3.7 Oprations disponibles sur une file priorit


Pour finir, nous noterons l'existence de l'algorithme gnrique make_heap dont le but est de fournir une structure
de tas une structure de donnes indexe (essentiellement vecteur ou DQ). Les structures obtenues se manipulent
l'aide de deux fonctions spcialises nommes push_heap et pop_heap. Bien que ces fonctionnalits puissent
paratre attractives, il faut les utiliser avec parcimonie car leurs performances sont nettement infrieures celles du
type priority_queue.
Concluons l'tude des files priorit par un petit exemple : nous souhaitons crer un petit programme qui gnre
argv[1] nombres pseudo alatoires tris dans l'ordre dcroissant. Une fois de plus, nous utilisons les classes Entier
et GenAlea.

Le droulement du programme est trs simple :


1
2
3

Dclaration d'un type file priorit sur le type Entier, bas sur une DQ d'Entier et utilisant la comparaison par
valeur infrieure.
Remplissage de la file priorit avec les valeurs issues du gnrateur de nombres pseudo alatoires
Tant que la file priorit n'est pas vide, affichage du meilleur lment puis extraction de cet lment.

Programme 3.6 Utilisation d'une file priorit


#include
#include
#include
#include

<stdlib.h>
<iostream>
<queue>
<deque>

#include "Entier.hxx"

- 38 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Programme 3.6 Utilisation d'une file priorit


#include "Genera.hxx"

int main(int argc, char *argv[])


{
typedef std::priority_queue<Entier,
deque<Entier>,
less<Entier>
> FilePrioInt;
FilePrioInt fileAlea;
GenAlea
generateur(time(0));
int
nbAlea=((argc > 1) ? atoi(argv[1]) : 10);
for (int compteurAlea=0;compteurAlea<nbAlea;compteurAlea++)
{
fileAlea.push(generateur());
}
while (!fileAlea.empty())
{
cout << fileAlea.top() << " ";
fileAlea.pop();
}

cout << endl;


return 0;

La sortie de ce programme est trs simple : il s'agit tout simplement d'une ligne d'entiers tris par ordre dcroissant.

III-B-6 - Les conteneurs associatifs


Les conteneurs associatifs sont trs particuliers. En effet leur structure repose sur la notion de paire (clef, valeur).
Tout accs aux lments contenus l'intrieur des ces types associatifs se fait par l'intermdiaire de ces clefs, y
compris les accs fournis par des itrateurs. En revanche, nous obtenons des mthodes de slection des lments
trs puissantes :

Elment(s) associs une valeur de clef particulire


Liste d'lments dont la clef est suprieur / infrieure une valeur de rfrence
Liste d'lments dont la clef est comprise l'intrieur d'une plage

Vous notez la prsence d'un pluriel facultatif la premire clause de cette numration. En effet, les conteneurs
associatifs sont disponibles en deux grandes variantes :

Les associations simples o l'on ne peut associer qu'une seule valeur une mme clef
Les associations multiples o une clef peut permettre d'accder plusieurs valeurs.
Du fait de cette double particularit, la plupart des algorithmes gnriques ne fonctionnent
pas sur les conteneurs associatifs.

La STL propose deux types de conteneurs associatifs :

Les ensembles : set pour un ensemble simple, multiset pour un ensemble multiple
Les map : map pour une map simple, multimap pour une map multiple.)

Dans le cas des ensembles, la valeur et la clef sont confondues : l'ordonnancement se fait sur les valeurs des
lments. Dans le cas des map , vous devez fournir le couple (clef, valeur) complet et les lments sont stocks
dans l'ordre des clefs.

- 39 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Ces conteneurs tant des collections ordonnes, vous devrez fournir un prdicat lors de la construction de l'objet, le
plus souvent sous la forme d'un objet foncteur, moins que votre compilateur n'accepte les arguments par dfaut
des template, auquel cas, less<type_clef> est assum par dfaut.

Les types associatifs exportent en public les types value_type et key_type respectivement associs au type
des valeurs et au type des clefs.

Dans le cas de set ces deux types sont identiques

Dans le cas de map, key_type est associ au type de la clef (on s'en doutait un peu) et value_type est
une paire (const type_clef, type_valeur) o type_valeur est le type des lments ordonner en fonction
des clefs.
Mme si l'on connat bien le type des lments que l'on manipule, il est toujours
prfrable d'utiliser les typedef type_associatif::value_type dans le cas de s valeurs ou
type_associatif::key_type lorsque l'on a besoin de rfrencer une clef.

Les types associatifs exportent galement le type key_compare, gal au type du prdicat pass en template.
De la mme manire qu'il vaut mieux utiliser le typedef key_value, prfrez key_compare l'argument du
template de cration
Dans le mme ordre d'ide, les conteneurs associatifs sont galement pourvus du type value_compare. Dans
le cas de set, celui ci est strictement identique key_compare alors que ce traitement est diffrenci pour les
map . En effet, dans ce cas la comparaison est double critre.

En premier lieu sur les clefs

Si les clefs sont identiques, la comparaison porte alors sur les valeurs

Nombre d'oprations tant gres par des paires, nous consacrons notre premire rubrique l'tude de ce type.

III-B-6-a - Le type pair


Accessible via #include <utility> le type pair est des plus prcieux lors de la manipulation des types associatifs.
Il est rare que vous dclariez vous mme un type pair. En effet, vous l'utiliserez plus souvent de faon implicite au
retour d'une mthode de la STL ou via les typedef value_type des map.
Voici la dfinition du type pair (rappelons qu'en C++ une struct est une classe dont tous les membres sont publiques
par dfaut):

Programme 3.7 Dfinition du type pair


template <class T1, class T2>
struct pair
{
T1 first;
T2 second;
pair (const T1& x, const T2& y);
};

Le type pair ne possde pas de fonction membre mais un constructeur ; l'accs aux deux membres respectivement
nomms first et second se faisant de manire directe.
Les oprateurs == et < sont redfinis pour les type pair avec les comportements habituels.
Notons galement l'existence de la fonction make_pair permettant de construire une paire partir de deux valeurs
quelconques et dfinie par :

- 40 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Programme 3.8 Dfinition de la fonction make_pair


template <class T1, class T2>
pair<T1,T2> make_pair (const T1 &a, const T2 &b)
{
return pair<T1,T2>(a,b);
}

Cette fonction est vraiment pratique car elle permet de crer une paire sans avoir spcifier explicitement le type de
cette dernire (c'est la fonction qui s'en charge). Le (micro) fragment de programme suivant montre qu'il est vraiment
facile de crer une paire quelconque l'aide de cette fonction.

Programme 3.9 Utilisation de make_pair


#include <utility>
#include <string>
#include <iostream>
int main(int, char**)
{
int i=3;
string s("Chane);
cout << make_pair(i,s).second << endl;
// le retour de make_pair de type pair<int,string>
// l'affichage concernera donc uniquement la chaine
return 0;
}

III-B-6-b - Itrateurs et conteneurs associatifs


Bien qu'ils soient inadapts la plupart des algorithmes gnriques (du fait de leur structure particulire), les
conteneurs associatifs ne sont pas allergiques, loin de la, la notion d'itrateur.
Les conteneurs associatifs peuvent fournir des itrateurs bidirectionnels l'aide des mthodes habituelles (begin,
end, rbegin, rend).
En outre, les mthodes de recherche d'lments, telles que, par exemple, find renvoient galement ce genre
d'itrateurs.

III-B-6-c - Mthodes et fonctions communes aux types set et map


Du fait de leurs grandes ressemblances, les oprations disponibles sur les types set et map sont trs semblables.
Collections ordonnes d'lments, les types set et map n'autorisent que des oprations limites sur les lments :

Insertion d'un ou plusieurs lments


Retrait d'un ou plusieurs lments
Recherche d'lments

Toutes ses oprations sont prvues pour tre excutes avec une complexit au pire logarithmique !
Quelques petites diffrences nous empchent de rassembler toutes les fonctionnalits dans un mme tableau. Nous
ne donnerons dans cette rubrique que les mthodes rigoureusement identiques la signification de value_type et
key_type prs ! Nous rappelons galement que dans le cas d'un set, les notions de clef et de valeur sont confondues.

- 41 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Mthodes communes aux conteneurs


Renvoie true si le conteneur est vide
Nombre d'lments prsents dans le
conteneur
size_type max_size () const;
Nombre maximal d'lments que peut
dtenir le conteneur
Accs l'objet foncteur prdicat
key_compare key_comp () const;
Renvoie l'objet foncteur prdicat du
conteneur
Insertion d'lments
pair<iterator, bool> insert (const
Insre un lment dans le conteneur et
value_type&);
renvoie une paire constitue d'un itrateur
positionn sur l'emplacement du nouvel
lment et d'un boolen indiquant si
l'opration a russi ou non. Si le boolen est
faux, la valeur de l'itrateur renvoy n'a pas
de signification
template <class InputIterator> void insert
Insertion d'lments compris entre deux
(iterator, InputIterator, InputIterator);
itrateurs. Notez que c'est une fonction
membre template et que votre compilateur
doit tre en mesure de les supporter
Suppression d'lments
void erase (iterator);
Supprime l'lment spcifi par l'itrateur
size_type erase (const key_type&);
Supprime l'lment spcifi par sa clef (ou
sa valeur pour un set)
void erase (iterator, iterator);
Supprime les lments compris entre les
deux itrateurs
Accs aux lments
set : iterator find (const key_value&) const;
Compte le nombre d'objets associs une
map : iterator find (const key_value&);
clef particulire. Dans le cas d'un conteneur
const_iterator find (const key_value&) const; simple cela ne peut tre que 0 ou 1 ; dans le
cas d'un ensemble multiple, n'importe quelle
valeur entire naturelle.
Attention ! les mthodes suivantes diffrent par
l'utilisation de const dans les deux conteneurs
set : iterator find (const key_value&) const;
Renvoie un itrateur sur l'lment (ou
map : iterator find (const key_value&);
le premier lment dans le cas d'un
const_iterator find (const key_value&) const; conteneur multiple) dont la clef est passe
en argument. Renvoie this->end() si aucun
lment ne correspond au critre de
recherche
set : iterator lower_bound (const key_type
Renvoient respectivement un itrateur sur : &x) const; iterator upper_bound (const
Le premier lment de clef infrieure x - Le
key_type &x) const; map : iterator
dernier lment de clef suprieure x
lower_bound (const key_type &x);
const_iterator lower_bound (const key_type
&x) const; (idem upper_bound)
set : pair<iterator, iterator>
Renvoie la paire d'itrateurs
equal_range (const key_type& x)
<lower_bound(x),upper_bound(x)> La
const; map : pair<iterator,iterator>
mthode equal_range renvoie une paire
equal_range (const key_type& x)
d'itrateurs encadrant les lments associs
pair<const_iterator,const_iterator>
une mme valeur de clef.
equal_range (const key_type& x) const;
bool empty () const;
size_type size () const;

Tableau 3.8 Oprations identiques sur les deux conteneurs set et map
- 42 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

III-B-6-d - Le type ensemble


Voici le descriptif des fonctions membres spcifiques set :

value_compare value_comp () const;


void swap (set<Key, Compare>&);

Renvoie l'objet foncteur prdicat de


l'ensemble, identique key_comp
Echange les lments de this avec ceux de
l'autre ensemble de mme type pass en
paramtre

Tableau 3.9 Les fonctions membres spcifiques set


En outre, en plus des habituels tests d'galit et d'infriorit (== et <), la plupart des oprations sur les ensembles sont
fournies en tant que fonctions externes. Toutes ces fonctions ont, l'exception de includes qui renvoie un boolen,
la mme signature, laquelle se dcline en deux versions :

Programme 3.10 signature des oprations ensemblistes


itrateurSortie fonction(itrateur debutGauche, itrateur finGauche,
itrateur debutDroite, itrateur finDroite)
itrateurSortie fonction(itrateur debutGauche, itrateur finGauche,
itrateur debutDroite, itrateur finDroite,
prdicat comp)

Bien entendu, il faut que les itrateurs soient positionns sur des ensembles pour que cela fonctionne correctement.
Attention ! (pige c- -), par dfaut, tout ce beau monde travaille avec l'oprateur < quel que soit l'oprateur fourni
pour la construction des set. Toutefois, il est possible de changer ce comportement en ajoutant un prdicat en dernier
argument (deuxime forme).
Notez galement que ces fonctions renvoient un itrateur de type output sur l'ensemble
construit et non l'ensemble lui mme ce qui peut paratre fcheux. La liste complte de
ces fonctions est la suivante :

Includes
set_union
set_intersection
set_difference
set_symmetric_difference

Renvoie vrai si le second ensemble est


inclus dans le premier
Effectue l'union de deux ensembles en
supprimant les doublons
Effectue l'intersection de deux ensembles
c'est dire la liste des lments prsents
dans les 2 ensembles
Recherche la liste des lments prsents
dans A non prsents dans B
Recherche la liste des lments prsents
dans A non prsents dans B laquelle
s'ajouter la liste des lments prsents dans
B non prsents dans A

Tableau 3.10 Fonctions globales s'appliquant au type set

- 43 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

III-B-6-e - Le type map


Le type map est un peu plus compliqu que set et possde donc plus de mthodes propres. En outre, nous avons
pu remarquer dans les paragraphes prcdents que la gestion de la constitude sur les accs aux lments est plus
complique que dans le cas de set. En effet, toutes les mthodes d'accs sont doubles selon qu'elles renvoient
ou non des itrateurs const.
Plus fort encore , le type map simple redfinit l'oprateur crochet de manire renvoyer la valeur d'un lment
accd par sa clef. En sus du ct minemment pratique ce cet oprateur, le fonctionnement du conteneur devient
par certains cts similaire celui d'un vecteur ou d'une DQ et les map deviennent donc utilisables par tous les
algorithmes utilisant de l'indexation pure ! En particulier (ne le dites personne) l'auteur arrive utiliser les map
comme base pour des tas au prix d'une certaine gymnastique il est vrai !
Voici donc la liste des mthodes spcifiques au type map :

value_compare value_comp () const;


void swap (map<Key, Compare>&);
T& operator[] (const key_type& x);

Renvoie un objet foncteur prdicat de


comparaison des paires (clef, valeur)
Echange les lments de this avec ceux
de l'autre map de mme type pass en
paramtre
Le fameux oprateur d'indexation. Attention,
il ne fonctionne que sur les map
simples ! Utilis en criture, il ajoute un
nouvel lment la map . Si un lment
de mme clef est dj prsent, aucune
action n'est entreprise. En lecture, son
fonctionnement est quelque peu compliqu :
- Si un lment de clef x est prsent, alors sa
rfrence est renvoye - Sinon, une nouvelle
entre de clef x est cre dans la map ,
la valeur associe est T() d'o la ncessit
d'un constructeur par dfaut pour le type
valeur ! Pour conclure sur cet oprateur, je
dsapprouve son utilisation en lecture sans
appel pralable count !

Tableau 3.11 Oprations spcifiques map

III-B-6-f - Un exemple de map


L'exemple suivant cre une map associant une chane un entier. Il illustre l'utilisation de l'indexation, de find et de
count. L'utilisation de equal_range, lower_bound et upper_bound est laisse l'exemple suivant sur les multimap.
Les commentaires du programme sont affichs par le programme et donc directement inclus dans sa sortie cran,
(figure suivant le programme)

Programme 3.11 Utilisation de map


#include <string>
#include <map>
#include <iostream>
typedef std::map<int, string, less<int> > MapIntString;
typedef MapIntString::iterator MapIntStringIt;
typedef MapIntString::value_type PairIntString;

- 44 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Programme 3.11 Utilisation de map


ostream &operator<<(ostream &a, const PairIntString &b)
{
a << "Clef : " << b.first << " Valeur : " << b.second;
return a;
}
int main(int, char**)
{
MapIntString map1;
MapIntStringIt itCourant;
map1[1]="premier";
map1[2]="second";
map1[3]="troisieme";
cout << " Affichage avec acces indexe" << endl;
for (int compteur=0;compteur<4;compteur++)
cout << map1[compteur] << " zz ";
cout << endl;
cout << " Affichage avec une paire d'iterateurs " << endl;
itCourant=map1.begin();
while (itCourant != map1.end())
cout << *(itCourant++) << " zz ";
cout << endl;
cout << " Affichage avec copy " << endl;
std::copy(map1.begin(),
map1.end(),
ostream_iterator<PairIntString>(cout, " ZZ "));
cout << "Tentative d'acces a un element non present : index 17" << endl;
cout << map1[17] << endl;
cout << "Affichage : remarquez la presence d'un element fictif sur la
clef 17 insere pas l'operateur []" << endl;
std::copy(map1.begin(),
map1.end(),
ostream_iterator<PairIntString>(cout, " ZZ "));
cout << endl;
cout << "Recherche avec find des elements presents " << endl;
cout << "Recherche de la clef 3 : pas de probleme ";
MapIntString::iterator itRecherche=map1.find(3);
if (itRecherche != map1.end())
{
cout << (*itRecherche).second << endl;
}
else
{
cout << "Pas trouve" << endl;
}
cout << "Recherche de la clef 13 non presente ";
itRecherche=map1.find(13);
if (itRecherche != map1.end())
{
cout << (*itRecherche).second << endl;
}
else
{
cout << "Pas trouve" << endl;
- 45 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Programme 3.11 Utilisation de map


}

cout << "Autre technique : utilisez count" << endl;


cout << "Nb de clefs 1 " << map1.count(1) << endl;
cout << "Nb de clefs 13 " << map1.count(13) << endl;
cout << "Plus interessant : Nb de clefs 17 " << map1.count(17) << endl;
cout << "Constatation : le systeme a ajoute des valeurs nulles
(constructeur par defaut) aux emplacements vides" << endl;
cout << "Moralite : toujours verifier par un appel a find ou count la
presence d'un element" << endl;
cout << "Effacage de l'element fictif 17" << endl;
map1.erase(17);
cout << "Affichage pour verifier : " << endl;
std::copy(map1.begin(),
map1.end(),
ostream_iterator<PairIntString>(cout, " zz "));
cout << endl;
cout << "Il a bien disparu !" << endl;
cout << "Tentative d'insertion d'un element dont la clef est deja
presente " << endl;
cout << "Tentative de remplacement de (2,second) par (2,zzDeux) " <<
endl;
map1.insert(MapIntString::value_type(2,"zzDeux"));
cout << "Affichage pour verifier" << endl;
std::copy(map1.begin(),
map1.end(),
ostream_iterator<PairIntString>(cout, " ZZ "));
cout << endl;
cout << "Comme vous pouvez le voir, ca ne change rien du tout :( " <<
endl;
cout << "En revanche, il est possible d'ajouter ou de modifier une
valeur a l'aide de l'indexation" << endl;
map1[2]="deuxieme";
map1[5]="cinquieme";
copy(map1.begin(), map1.end(),
ostream_iterator<PairIntString>(cout, " ZZ "));
cout << endl;
}

return 0;

Et voici la sortie cran :

- 46 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Figure 3.4 Sortie cran du programme d'exemple de map

III-B-6-g - Un exemple de multimap


L'exemple suivant traite d'une base de donnes de communes indexes par le code postal. Elle montre comment
utiliser find, equal_range, lower_bound et upper_bound. Selon l'implmentation de la STL dont vous disposez, il vous
faudra peut tre utiliser #include <multimap> en lieu et place de #include <map> pour cet exemple.
Notez que la premire version de l'affichage de la multimap (par parcours de la paire
d'itrateurs) n'envoie l'cran que les chanes de caractres et pas leurs index alors que
l'utilisation de copy nous fournit les deux.
Lorsque vous cherchez des lments avec equal_range, il est possible de savoir si la recherche a chou en
comparant le rsultat obtenu avec la paire (conteneur.end(), conteneur.end()). Il est galement possible de tester la
prsence d'un ou plusieurs lments avec count.

Programme 3.12 Utilisation d'une multimap pour la gestion d'une base de code postaux
#include <string>
#include <map>
#include <iostream>
// multi map associant plusieurs chaines (les noms des communes)
// un entier (le code postal)
typedef std::multimap<int, std::string, std::less<int> > MultiMapIntString;
typedef MultiMapIntString::iterator MultiMapIntStringIt;
typedef MultiMapIntString::value_type PairIntString;
typedef std::pair<MultiMapIntStringIt, MultiMapIntStringIt> PaireIterateurs;
// Oprateur d'affichage d'une paire (entier, chane)
ostream &operator<<(ostream &a, const PairIntString &b)
{
a << "Clef : " << b.first << " Valeur : " << b.second;
return a;
- 47 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Programme 3.12 Utilisation d'une multimap pour la gestion d'une base de code postaux
}

// Oprateur d'affichage permettant de "dumper l'intgralit des valeurs


// comprises entre deux itrateurs
ostream &operator<<(ostream &a, const PaireIterateurs &b)
{
std::copy(b.first,
b.second,
ostream_iterator<PairIntString>(a," "));
return a;
}
int main(int, char**)
{
MultiMapIntString map1;
MultiMapIntString::iterator itCourant;
MultiMapIntString::iterator itFin;
PaireIterateurs its;
// Remplissage de la "base
map1.insert(MultiMapIntString::value_type(63000,"Clermont Ferrand"));
map1.insert(MultiMapIntString::value_type(63100,"Montferrand"));
map1.insert(MultiMapIntString::value_type(63100,"Les Vergnes"));
map1.insert(MultiMapIntString::value_type(63100,"La Plaine"));
map1.insert(MultiMapIntString::value_type(63400,"Chamalieres"));
map1.insert(MultiMapIntString::value_type(63400,"Voie Romaine"));
map1.insert(MultiMapIntString::value_type(63800,"Cournon d'Auvergne"));
map1.insert(MultiMapIntString::value_type(63800,"Perignat sur Allier"));
map1.insert(MultiMapIntString::value_type(63800,"Saint Georges sur Allier"));
// Affichage de la multimap par une boucle sur les itrateurs
itCourant=map1.begin();
itFin=map1.end();
while (itCourant != itFin)
{
cout << (*itCourant).second << " zz ";
itCourant++;
}
cout << endl;
// Affichage de la multimap par une copie sur itrateur de flux en sortie
std::copy (map1.begin(),
map1.end(),
ostream_iterator<PairIntString>(cout, " zz "));
cout << endl;
// Recherche du premier lment associ clef 63800
cout << "Resultat de find sur la clef 63800" << *(map1.find(63800)) << endl;
// Recherche de tous les lments associs la clef 63800
cout << "Resultat de equal_range sur la clef 63800 " ;
cout << map1.equal_range(63800) << endl;
// Recherche d'un lment avec equal_range
its=map1.equal_range(3000);
if (its == PaireIterateurs(map1.end(),map1.end()))
{
cout << "Pas Trouve" << endl;
}
its=map1.equal_range(63100);
if (its == PaireIterateurs(map1.end(),map1.end()))
{
cout << "Pas Trouve" << endl;
}
else
{
- 48 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Programme 3.12 Utilisation d'une multimap pour la gestion d'une base de code postaux
cout << its << endl;

// Utilisation de lower et upper bound


cout << "Tentative de lower/upper bound" << endl;
its.first=map1.lower_bound(63100);
its.second=map1.upper_bound(63400);
cout << its << endl;
// (lower_bound(i), upper_bound(i)) == equal_range(i)
cout << "Simulation de equal_range avec lower/upper bound" << endl;

cout << "Equal range " << map1.equal_range(63400) << endl;


cout << "Lower/upper " << PaireIterateurs(map1.lower_bound(63400),
map1.upper_bound(63400)) << endl;
return 0;

Le rsultat l'cran est le suivant :

Figure 3.5 Rsultat d'excution du programme de test sur les multimap

III-C - Les itrateurs


Tout au long de la prsentation des conteneurs, nous n'avons cess d'utiliser des itrateurs. De mme, tous les
algorithmes gnriques qui permettent d'utiliser les conteneurs reposent sur cette notion.

III-C-1 - Dfinition et premier contact


Un itrateur est une variable qui repre la position d'un lment dans un conteneur.

Il existe deux positions bien spcifiques :

Le dbut d'une collection, c'est dire son premier lment. Cet itrateur est renvoy par la mthode begin()
La fin d'une collection, c'est dire l'lment positionn juste aprs le dernier. Cet itrateur est renvoy par la
mthode end()

L'lment le plus important noter est le suivant : Les itrateurs ont un fonctionnement identique celui des pointeurs
dans un tableau. En effet, considrez le code suivant :

- 49 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

int tab[10];
int *p;
int i=0;
for (p=tab;i<10;i++,p++)
cout << *p << " " << endl;

Le pointeur *p joue exactement le rle d'un itrateur : rfrencer un lment. L'oprateur * permet d'accder
l'lment plac sous l'itrateur ; l'oprateur ++ tant ddi l'avancement de l'itrateur.
Dans la boucle prcdente, le test d'arrt porte sur la valeur d'un compteur entier. Supposons que nous dcidions
de faire tous les tests sur un pointeur, nous obtiendrions alors :
int tab[10];
int *p;
int *borne=tab+10;
for (p=tab;p<borne;p++)
cout << *p << " " << endl;

Ce qui, en terme de STL s'crira :


vector<int> tab(10);
for (vector<int>::iterator p=tab.begin();p<tab.end();p++)
cout << *p << " " << endl;
et le tour est jou !
Vous voyez c'est pas compliqu d'utiliser un itrateur !

III-C-2 - Les diffrents types d'itrateurs


Il existe diffrents types d'itrateurs lis divers types d'oprations ainsi qu'aux conteneurs sur lesquels ils oprent.
Les oprations suivantes seront plus ou moins disponibles selon le type d'itrateur auquel vous serez confront :
Drfrencement : accs l'lment (soit en lecture, soit en criture) contenu dans le conteneur l'emplacement
point par l'itrateur
Dplacement de l'itrateur : en avant, en arrire ou de faon alatoire
Comparaison de deux itrateurs : afin de savoir s'ils font rfrence au mme emplacement dans le conteneur

Les itrateurs sont regroups selon deux grands critres :

Le type d'accs aux lments (lecture et / ou criture)


Le type de mouvement (en avant, en arrire, alatoire)

En fonction de leurs spcificits, les collections seront mme de gnrer certains types d'itrateurs.
Le tableau suivant rcapitule quels types d'itrateurs vous pourrez rencontrer selon le conteneur, sachant que les
types queue, stack et priority_queue ne fournissent jamais d'itrateur

Input
Output
Forward

Type

Dplacement
Aucun
Aucun
Avant

Accs
Lecture
Ecriture
Lecture / Ecriture

Gnration
Gnration
Classe input_iterator
Classes
output_iterator,
font_inserter et

- 50 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

Bidirectionnel

Avant / Arrire

Lecture / Ecriture

Alatoire

Avant /Arrire/
Alatoire

Lecture / Ecriture

back_inserter (utiliss
par les algorithmes
gnriques
d'insertion)
Vector, deque, list,
set, multiset, map,
multimap
Vector, deque

Tableau 3.12 Les diffrents types d'itrateurs


En outre, les itrateurs existent en version const et non const. Drfrencer un itrateur non const renvoie une
rfrence sur un objet contenu dans le conteneur.
Cette rfrence pourra tre utilise en tant que lvalue, c'est dire gauche d'un signe = ; en particulier, vous pourrez
changer l'objet prsent dans le conteneur cet emplacement. Avec un itrateur const, non seulement vous ne pourrez
pas utiliser le retour comme lvalue, mais vous pourrez seulement appliquer des mthodes const sur l'objet dsign !
Bien entendu, un conteneur const renverra systmatiquement des itrateurs const.

III-C-3 - Comment obtenir un itrateur ?


Il existe plusieurs manires d'obtenir un itrateur :

Les mthodes begin() et end() renvoient respectivement un itrateur sur le dbut (premier lment) et la fin
(lment aprs le dernier) d'un conteneur

Notons immdiatement qu'il existe des itrateurs bizarres : les reverse iterators, qui reculent sous l'effet de l'oprateur
++. Ils s'obtiennent l'aide des mthodes rbegin() et rend() et sont disponible en version const et non const.
Ils s'utilisent essentiellement lorsque vous devez parcourir une collection rebrousse poil, la plupart des algorithmes
de parcours utilisant l'oprateur ++.

Plusieurs mthodes ou algorithmes renvoient galement des itrateurs


Construire directement un itrateur l'aide de son constructeur. C'est notamment le cas pour les itrateurs de
flux ou les itrateurs d'insertion

Tous les algorithmes de type find, lower_bound ou upper_bound qui recherchent des lments et
renvoient des itrateurs sur leurs emplacements. Toute recherche infructueuse se soldant par le renvoie
de la borne suprieure de recherche ou de conteneur.end().

Les fonctions d'oprations ensemblistes

etc

III-C-4 - Les itrateurs de flux


Ils permettent de dumper une squence d'lments (en provenance d'un conteneur et encadrs par des itrateurs)
vers un flux ou encore de lires des lments depuis un flux vers un conteneur.
Les itrateurs de flux de sortie sont construits grce au constructeur :
ostream_iterator<TypeAEcrire>(flux_de_sortie,chaineDeSeparateur)

Nous les avons rgulirement utiliss pour toutes les oprations de sortie dans les exemples sur les conteneurs.
Toutefois, nous redonnons ici un exemple permettant d'afficher le contenu d'un vecteur l'cran, chaque lment
- 51 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

tant spar par un saut de ligne. L'algorithme copy est utilis dans la plupart des cas pour envoyer les lments
vers l'itrateur de sortie.
vector<int> v;
// code omis
copy (ostream_iterator<int>(cout,\n),v.begin(),v.end());

Les itrateurs de flux en entre sont un peu plus compliqus. En effet, ils ont besoin de 2 paramtres template :

Le type de donnes lire


Un second type que l'on doit fix ptrdiff_t sous peine d'ennuis

Appeler l'oprateur ++ sur un tel itrateur lit un objet dans le flux et le stocke dans une structure interne. L'oprateur
* permet alors d'y accder.
Le constructeur d'un itrateur en entre de flux ne prend qu'un seul paramtre : le flux lire. En l'absence de
paramtre, le constructeur fournit un itrateur servant de comparaison et modlisant EOF. L'exemple suivant permet
de clarifier les ides :

Programme 3.13 Essai des itrateurs de flux en entre


#include <iostream>
#include <fstream>
#include <deque>
int main(int, char**)
{
ifstream f("toto");
deque<int> t;
istream_iterator<int,ptrdiff_t> entree(f), eof;
while (entree != eof)
{
t.push_back(*entree);
entree++
}

copy(t.begin(),t.end(),ostream_iterator<int>(cout," "));
cout << endl;
f.close();
return 0;

Ce petit programme ne fait que lire un fichier jusqu' la fin, stocker le contenu dans une DQ avant de le renvoyer
l'cran.
Le code suivant n'utiliser pas d'intermdiaire :
#include <iostream>
#include <fstream>
#include <deque>
int main(int, char**)
{
ifstream f("toto");
istream_iterator<int,ptrdiff_t> entree(f), eof;
copy(entree,eof,ostream_iterator<int>(cout," "));
- 52 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

cout << endl;


f.close();
return 0;

- 53 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

IV - Annexe A : un exemple de makefile


Le programme suivant indique le Makefile utilisable pour gnrer l'excutable associ divers fichiers source dont
l'extension est .cpp.

Programme 4.1 Makefile gnrique pour le C++


#On purge la liste des suffixes
.SUFFIXES:
#On ajoute simplement les extensions dont l'on a besoin
.SUFFIXES: .cpp .o
#Executable
EXEC=princi
#Liste des fichiers objet
OBJETS=Vehicule.o Depannage.o Princi.o RandomGenerator.o \
MarsagliaGenerator.o
#Liste des fichiers source
SOURCES=Vehicule.cpp Depannage.cpp Princi.cpp RandomGenerator.cpp \
MarsagliaGenerator.cpp
# avec GnuMake : SOURCES=${OBJETS:%.o=%.cpp}
#Compilateur et options de compilation
CCPP=g++
CCFLAGS=-g -Wall -ansi -pedantic
#Regle explicite de construction de l'executable
${EXEC}:${OBJETS} makefile
${CCPP} -o ${EXEC} ${OBJETS}
#Regle implicite de construction des fichiers objet partir
#des fichiers .cpp
.cpp.o:
${CCPP} -c ${CCFLAGS} $< -o $@
# avec GnuMake
# %.o : %.cpp
# ${CCPP} -c ${CCFLAGS} $< -o $@
#gestion des dpendances
depend:
sed -e "/^#DEPENDANCIES/,$$ d" makefile > dependances
echo "#DEPENDANCIES" >> dependances
${CCPP} -MM ${SOURCES} >> dependances
cat dependances > makefile
rm dependances
#DEPENDANCIES
Depannage.o: Depannage.cpp Depannage.hxx
MarsagliaGenerator.o: MarsagliaGenerator.cpp MarsagliaGenerator.hxx \
RandomGenerator.hxx
Princi.o: Princi.cpp Voiture.hxx Vehicule.hxx Camion.hxx Parc.hxx \
Adapter.hxx Helico.hxx MarsagliaGenerator.hxx RandomGenerator.hxx
RandomGenerator.o: RandomGenerator.cpp RandomGenerator.hxx
Vehicule.o: Vehicule.cpp Vehicule.hxx Depannage.hxx \
RandomGenerator.hxx

Vous noterez les points importants suivant :

.SUFFIXES: purge la liste des rgles implicites. En particulier, la liste des extensions autorises pour les
rgles implicites est vide.

- 54 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

.SUFFIXES: .cpp .o ajouter les extensions .cpp et .o la liste des extensions valides pour les rgles
implicites. Ce comportement en ajout justifie la purge prcdente qui permet de repartir d'une situation
connue : le vide !
La rgle .cpp.o: constitue un bon exemple de rgle implicite permettant de crer un fichier .o partir d'un
fichier .cpp. Notez l'utilisation des macros $< et $@ respectivement associes au membre gauche et au
membre droit de la rgle.
Soit, dans notre exemple : $< fichier.cpp et $@ fichier.o
La rgle depend permet de crer automatiquement des rgles de dpendances. Elle utilise pour cela l'option MM de gcc et une petite instruction sed !
Gnu make permet de rajouter des rgles plus puissantes ainsi qu'une syntaxe plus intuitive pour les rgles
implicites.

- 55 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/

La bibliothque standard du C++ par Bruno Garcia

V - Annexe B : Tables des illustrations


Figure 2.1 Espaces de nommage avec noms conflictuels
Figure 2.2 Hirarchie des exceptions de la STL
Figure 2.3 Sortie cran du programme prcdent
Figure 2.4 Rsultat cran du programme prcdent
Figure 3.1 Rsultat du programme d'essai sur vector
Figure 3.2 Sortie cran de la dmonstration de list
Figure 3.3 Sortie cran du programme de test piles / files
Figure 3.4 Sortie cran du programme d'exemple de map
Figure 3.5 Rsultat d'excution du programme de test sur les multimap
Programme 2.1 dclaration et dfinition d'un espace de nommage
Programme 2.2 Exemple de collision entrane par l'utilisation de la cause using namespace
Programme 2.3 Exemple d'utilisation de la clause using et des dangers inhrents
Programme 2.4 Exemple plus complet d'utilisation des alias
Programme 2.5 Exemple complet d'utilisation des espaces de nommage
Programme 2.6 Mini exemple de constructeurs de la classe string
Programme 2.7 Dclaration de la classe std::exception
Programme 2.8 exemple complet d'utilisation des exceptions de la STL
Programme 2.9 utilisation des type_info et de typeid
Programme 3.1 La classe Entier
Programme 3.2 Manipulations sur la taille des vecteurs
Programme 3.3 Dmonstration du type list
Programme 3.4 Les classes de gnrateurs GenAlea et GenLin
Programme 3.5 Programme de test piles et files
Programme 3.6 Utilisation d'une file priorit
Programme 3.7 Dfinition du type pair
Programme 3.8 Dfinition de la fonction make_pair
Programme 3.9 Utilisation de make_pair
Programme 3.10 signature des oprations ensemblistes
Programme 3.11 Utilisation de map
Programme 3.12 Utilisation d'une multimap pour la gestion d'une base de code postaux
Programme 3.13 Essai des itrateurs de flux en entre
Programme 4.1 Makefile gnrique pour le C++
Tableau 2.1 mthodes agissant sur la taille des chanes de caractres
Tableau 2.2 les mthodes gnrales d'ajout dans les squences
Tableau 2.3 Spcificits des diffrentes exceptions de la STL
Tableau 3.1 Les oprations disponibles sur toutes les squences lmentaires
Tableau 3.2 Mthodes spcifiques vector
Tableau 3.3 Oprations spficiques list
Tableau 3.4 Oprations spcifiques au type deque
Tableau 3.5 Oprations disponibles sur une file
Tableau 3.6 Oprations disponibles sur les piles
Tableau 3.7 Oprations disponibles sur une file priorit
Tableau 3.8 Oprations identiques sur les deux conteneurs set et map
Tableau 3.9 Les fonctions membres spcifiques set
Tableau 3.10 Fonctions globales s'appliquant au type set
Tableau 3.11 Oprations spcifiques map
Tableau 3.12 Les diffrents types d'itrateurs

- 56 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention
pralable de l'autorisation de l'auteur.

http://cpp.developpez.com/cours/stl/