2. C++ Avancé
2.6. Les Containers STL
Un container est une structure de données qui permet de stocker des éléments
de même type.
Au sein de la STL on distingue :
- les containers de séquences qui stockent les objets de manière linéaire : vector, list, array, ...
- les containers associatifs qui offrent la possibilité d'un accès rapide grace à l'utilisation de clés : set, multiset, map, multimap
2.6.1. array (C++11)
Il permet de modéliser les tableaux de taille constante.
#include <array>
#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;
int main() {
array<int, 10> a;
a.fill(2);
int sum = 0;
for (int i=0; i<a.size(); ++i) {
sum += a[i];
}
cout << "sum = " << sum << endl;
return 0;
}
2.6.2. valarray (C++11)
std::valarray and helper classes are defined to be free of certain forms of aliasing, thus allowing operations on these classes to be optimized similar to the effect of the keyword restrict in the C programming language. In addition, functions and operators that take valarray arguments are allowed to return proxy objects to make it possible for the compiler to optimize an expression such as v1 = a*v2 + v3; as a single loop that executes v1[i] = a*v2[i] + v3[i]; avoiding any temporaries or multiple passes.
source cppreference.com/valarray
L'utilisation de valarray se révèle assez différente des autres containers :
#include <iostream>
#include <valarray>
#include <algorithm>
#include <cstdlib>
#include <cmath>
using namespace std;
void test_1() {
cout << "====== TEST 1 ======" << endl;
// create valarray with initial values
valarray<float> v(10);
for (size_t i=0; i<v.size(); ++i) v[i] = sin(i * 4.0);
for (auto x : v) cout << x << " ";
cout << endl;
// compute sum, min, max
cout << "sum = " << v.sum() << endl;
cout << "min = " << v.min() << endl;
cout << "max = " << v.max() << endl;
// define mask_array to be all values greater than 0
valarray<bool> mask = v > 0.0f;
for (auto x : mask) cout << x << " ";
cout << endl;
// use mask_array to select values from v and put them
// in variable 'selected'
valarray<float> selected = v[mask];
for (auto x : selected) cout << x << " ";
cout << endl;
// apply square root on selected values
valarray<float> vs = sqrt(selected);
for (auto x : vs) cout << x << " ";
cout << endl;
}
void test_2() {
cout << "====== TEST 2 ======" << endl;
valarray<double> v1(10), v2(10), v3(10);
for (size_t i=0; i<v1.size(); ++i) {
v1[i] = i;
v2[i] = i*i;
}
v3 = v1 + v2;
for (auto x : v3) cout << x << " ";
cout << endl;
}
int main() {
test_1();
test_2();
return EXIT_SUCCESS;
}
====== TEST 1 ======
0 -0.756802 0.989358 -0.536573 -0.287903 0.912945 -0.905578 0.270906 0.551427 -0.991779
sum = -0.754
min = -0.991779
max = 0.989358
0 0 1 0 0 1 0 1 1 0
0.989358 0.912945 0.270906 0.551427
0.994665 0.955482 0.520486 0.742581
====== TEST 2 ======
0 2 6 12 20 30 42 56 72 90
2.6.3. vector
Il permet de modéliser les tableaux de taille variable. Il peut être manipulé comme un tableau
ou une pile.
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;
/**
* insert values in to vector and compute sum
*/
void test_1() {
vector<int> v;
for (int i=0; i<10; ++i) {
v.push_back(i+1);
}
int sum = 0;
for (int i=0; i<v.size(); ++i) {
sum += v[i];
}
cout << "sum = " << sum << endl;
}
/**
* create initial vector with 10 values and modify
*/
void test_2() {
vector<int> v(10);
// 0 0 0 0 0 0 0 0 0 0
fill(v.begin(), v.end(), 0);
// 1 1 1 1 1 0 0 0 0 0
fill_n(v.begin(), 5, 1);
// C++11
// 1 2 3 4 5 6 7 8 9 10
iota(v.begin(), v.end(), 1);
// 1 2 3 4 5 6 7 8 9 10 0 0 0 0 0 0 0 0 0 0
v.resize(20);
// 1 2 3 4 5 6 7 8 9 10 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
fill(v.begin() + 10, v.end(), -1);
}
/**
* main function
*/
int main() {
test_1();
test_2();
return 0;
}
2.6.4. list
le container list permet de modéliser une liste d'éléments. Il peut être manipulé comme un tableau
ou une pile.
Warning: file_get_contents(ens/inra/c2_stl_cont_list.cpp): Failed to open stream: No such file or directory in
/home/jeanmichel.richer/public_html/html_business.php on line
488
2.6.5. set
container associatif qui stocke de manière unique les éléments. Les éléments
sont rangés par ordre croissant par défaut. On peut spécifier une fonction de
tri utilisée pour l'insertion d'un nouvel élément.
#include <vector>
#include <set>
#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;
/**
* new ordering with reverse order
*/
struct Ordering {
bool operator()(int a, int b) {
return a > b;
}
};
/**
* main function
*/
int main() {
vector<int> v;
srand(19702013);
// -------------------------------------------
// fill vector with random values between 0 and 19
for (int i=0; i<100; ++i) {
v.push_back(rand() % 20);
}
// -------------------------------------------
// print vector
cout << "v = [";
for (int i=0; i<v.size(); ++i) {
cout << v[i] << " ";
}
cout << "]" << endl;
// -------------------------------------------
// create set from vector
set<int> s1(v.begin(), v.end());
cout << "s1 = {";
copy(s1.begin(), s1.end(), ostream_iterator<int>(cout, " "));
cout << "}" << endl;
// -------------------------------------------
// create set from vector with specific ordering
set<int, Ordering> s2(v.begin(), v.end());
cout << "s2 = {";
copy(s2.begin(), s2.end(), ostream_iterator<int>(cout, " "));
cout << "}" << endl;
return 0;
}
v = [16 18 7 18 13 17 11 6 6 0 10 12 3 15 0 14 0 14 5 19 5 10 6 19 9 10 9 5 0 0 8 16 19 7 6 12 4 10 18 2 10 0 15 6 7 7 0 7 13 17 18 18 19 4 17 9 7 6 6 7 19 7 3 18 14 1 10 11 11 0 13 14 0 8 12 19 7 12 7 1 2 5 19 1 2 9 2 9 7 1 16 6 8 11 4 2 4 6 13 16 ]
s1 = {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 }
s2 = {19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 }
2.6.6. map
container associatif qui stocke de manière unique les éléments sous forme
d'une clé et d'une valeur (paire).
#include <vector>
#include <map>
#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;
/**
* new ordering : reverse order
*/
struct Ordering {
bool operator()(int a, int b) {
return a > b;
}
};
/**
* main function
*/
int main() {
vector<int> v;
srand(19702013);
// -------------------------------------------
// fill vector with random values between 0 and 19
for (int i=0; i<100; ++i) {
v.push_back(rand() % 20);
}
// -------------------------------------------
// print vector
cout << "v = [";
for (int i=0; i<v.size(); ++i) {
cout << v[i] << " ";
}
cout << "]" << endl;
// -------------------------------------------
// create map to count number of occurrences
// of each value
// key = integer value,
// value = #occurrences in v
map<int, int> m;
map<int,int>::iterator it;
for (int i = 0; i<v.size(); ++i) {
it = m.find(v[i]);
if (it == m.end()) {
m[ v[i] ] = 0;
}
++m[ v[i] ];
}
for (it = m.begin(); it != m.end(); ++it) {
cout << (*it).first << " appears " << (*it).second << " times" << endl;
}
return 0;
}
v = [16 18 7 18 13 17 11 6 6 0 10 12 3 15 0 14 0 14 5 19 5 10 6 19 9 10 9 5 0 0 8 16 19 7 6 12 4 10 18 2 10 0 15 6 7 7 0 7 13 17 18 18 19 4 17 9 7 6 6 7 19 7 3 18 14 1 10 11 11 0 13 14 0 8 12 19 7 12 7 1 2 5 19 1 2 9 2 9 7 1 16 6 8 11 4 2 4 6 13 16 ]
0 appears 9 times
1 appears 4 times
2 appears 5 times
3 appears 2 times
4 appears 4 times
5 appears 4 times
6 appears 9 times
7 appears 11 times
8 appears 3 times
9 appears 5 times
10 appears 6 times
11 appears 4 times
12 appears 4 times
13 appears 4 times
14 appears 4 times
15 appears 2 times
16 appears 4 times
17 appears 3 times
18 appears 6 times
19 appears 7 times