- Architecture
-
C/C++ types are poor, and are mostly just a thin layer on top of the memory representation. This problem is especially acute with arrays and other data structures.
STL is a library providing both containers (such as vector) as well as algorithms, by means of the C++ templates with its main concern being performance and correctness.
Using templates solves the problem of implementing an algorithm for each of the possible types (Including user defined types)
But, The main STL challenge was the MxN problem ,with N containers and M algorithms.
How to avoid coding algorithms for each of the containers ?
Inheritance has 2 problems
- Inheriting from some base container has run time + space costs
- Although containers have overlapping behaviour it's not 100% compatible.
The solution that was chosen to avoid having to code algorithms for each of the containers is to entirely decouple the two and add another layer of abstraction in between
Containers
Algorithms
Iterators
Functors
Iterators are pointer like abstraction to an element within a container
int arr[] = {1,2,3};
int* pI = &arr[0];
*pI = 10; // sets the first element of arr to 10
++pI; // Advance pI to next element
vector<int> v {1,2,3};
vector<int>::iterator itr = v.begin();
*itr = 10; // sets the first element of v to 10
++itr; // Advance itr to next element
Similar semantics for Iterators
begin()
end()
1
3
2
Container
In fact arrays and containers can be used interchangeably
int arr[] = {1,2,3};
for(int* p = &arr[0]; p != &arr[0] + 3; ++p)
cout << *p <<endl;
for_each(&arr[0], &arr[0] + 3, [](int n) { cout << n << endl; } );
vector<int> v {11,22,33};
for(vector<int>::iterator itr = v.begin(); itr != v.end(); ++itr)
cout << *itr << endl;
for_each(v.begin(), v.end(), [](int n) { cout << n << endl; } );
there are 5 Iterators categories identifying the operations they support
Each iterator from the second group supports all the functionality in iterators mentioned before it.
C Pointer is considered a Random access iterator because it support all the operations a random access iterator dictates.
There are 2 types of containers
The user controls the order of the elements.
The vector<> is by far the most useful, and a replacement to the C array.
array, vector and deque all support fast random access to the elements. list supports bidirectional iteration, whereas forward_list supports only unidirectional iteration.
array does not support element insertion or removal.
vector supports fast element insertion or removal at the end. Any insertion or removal of an element not at the end of the vector needs elements between the insertion position and the end of the vector to be copied
Vector: Add - O(1) remove - O(N^2) Random Access - O(1)
The order of the containers is dictated by the values.
The first group requires the less than operator to be implemented, and is applying a strict weak ordering
The second requires a good hash function + Equality predicate
Maps element are pair<T1,T2> ordering is performed on T1
multimap, set, multiset do not have operator[]
include <algorithm>
Possible division:
Range insertion over back_inserter