Introduction à la STL§

Rappel§

La librairie standard C++§

La librairie standard C++ est composée:

Comme en Java, une bonne maîtrise du langage C++, c'est aussi une bonne maîtrise de la librairie standard.

La STL§

Sa force est

Conteneurs§

Quelques exemples§

Un conteneur est un ensemble structuré de données:

Consultez aussi http://www.cplusplus.com/.

Construction§

Tous les conteneurs sont paramétrables par le type d'éléments à contenir (via le mécanisme template) et ont un constructeur par défaut:

#include<vector>
#include<list>
#include<set>
#include<map>
...
std::vector<double> v1;
std::vector<std::string> v2;
std::list<int> l;
std::set<std::string> s;
std::map<std::string, int> m;

Les conteneurs ainsi créés sont vides.

Alimentation§

Les conteneurs qui satisfont le concept de Sequence ont une méthode insert() qui prend en paramètre la valeur à insérer.

s.insert("toto");

Les conteneurs qui satisfont en plus le concept BackInsertionSequence, comme std::vector ou std::list, ont une méthode push_back() pour ajouter à la fin du conteneur.

v1.push_back(2.0);

Paire§

Les std::map sont des ensembles de paires (clé-valeur). Les paires sont modélisés par la classe std::pair.

std::pair<std::string, int> p("janvier", 31);

Attention, dans std::map, ce sont des paires qui sont stockées; on insère donc des paires:

m.insert( p );

Ex.1. Map/Vector (10 min)§

Iterateurs§

Qu'est-ce que c'est ?§

Un iterateur est un objet léger donnant un moyen de parcourir, lire et/ou écrire les données d'un conteneur.

Ce sont une généralisation des pointeurs. En tant que tels, si it est un iterateur, on peut faire, entre autres opérations, it++ pour atteindre la donnée suivante et *it pour obtenir la donnée pointée.

Comment créer un iterateur ?§

Tous les conteneurs de la STL ont les types internes suivants

et fournissent des iterateurs par les méthodes suivantes

En général, on ne construit pas un iterateur de zéro, on en demande aux conteneurs.

Comment les utiliser ?§

Avec un itérateur, le parcours de tous les éléments d'un conteneur ressemble à ceci:

for (Conteneur::const_iterator it = leConteneur.begin();
     it != leConteneur.end(); it++)
{
  *it = 0; //initialisation a zero
}

On imite ainsi le code C, basé sur un pointeur:

int tab[N];
for (int* ptr = tab; ptr != (tab + N); ptr++)
{
  *ptr = 0;
}

En sens contraire§

De nombreux conteneurs supportent un parcours de leurs éléments dans les deux sens. Il suffit d'opter pour les bons itérateurs:

for (Conteneur::const_reverse_iterator it = leConteneur.rbegin();
     it != leConteneur.rend(); it++)
{
  ...
}

Concept de range§

Un range est un intervalle de données d'un conteneur implicitement décrit par une paire (ordonnée) d'itérateurs.

Par exemple, leConteneur.begin() et leConteneur.end() décrivent un range correspondant à l'ensemble des données du conteneur.

Pour une paire d'itérateurs (itb, ite), on suppose que:

Ex.2. Parcours (20 min)§

Algorithmes§

Quelle forme ont-ils ?§

Les algorithmes sont des fonctions dont les paramètres d'entrées sont des itérateurs sur un ou deux conteneurs (plus, pour certains un foncteur agissant sur les données) .

Cette interface sous forme de fonctions

Principaux algorithmes§

Sont disponibles après #include<algorithm>:

Consultez la liste des algorithmes

Ex.3. Algorithmes (15 min)§

Dans testVecteur.cpp:

Foncteurs§

Qu'est-ce que c'est ?§

Un foncteur est la généralisation d'une fonction. C'est un objet possédant l'opérateur (), qui admet le plus souvent aucun, un ou deux paramètres et retourne une valeur.

NB. Un predicat est un foncteur qui retourne une valeur de type bool.

Le foncteur se distingue d'une fonction en ce qu'il peut, comme tout objet, avoir un état.

Comment écrire un foncteur ?§

Pour créer un foncteur, l'étape cruciale consiste à surcharger l'opérateur () (la méthode s'appelle operator(), d'où les doubles parenthèses):

#include<cstdlib> //pour std::rand
class GenerateurAleatoire {
  public:
    int operator()() {
      return std::rand()%100;
    }
};

Après avoir instancier votre foncteur, vous pouvez l'utiliser comme une fonction:

MonGenerateurAleatoire g;
std::cout << g() << std::endl; //entre 0 et 99

Ajouter un état§

Dans cet example, on peut aussi bien utiliser une fonction:

int g() {
  return std::rand()%100;
}
...
std::cout << g() << std::endl; //entre 0 et 99

Mais, un foncteur est adaptable, sans modifier la liste des paramètres de l'opérateur ():

#include<cstdlib> //pour std::rand
class GenerateurAleatoire {
  public:
    int monMax;
    GenerateurAleatoire(int max): monMax(max) {}
    int operator()() {
      return std::rand()%monMax; //entre 0 et monMax-1
    }
};

Ex.4. Foncteurs/Algorithmes (20 min)§

Ce qu'il faut retenir§

La STL est composé de:

Elle est générique, conteneurs et algorithmes sont orthogonaux.

Elle est compatible avec le C, notamment grâce à la surcharge d'opérateurs, qui permet d'écrire des généralisations des pointeurs (itérateurs) et des fonctions (foncteurs).