T) STL Containers - kalinosia/cpp GitHub Wiki

  • Something what can store multiple elements of the same type
  • Container manages memory, which is needed to store its elements
  • Three classes of containers can be distinguished:
    • sequence containers
    • associative containers
    • unordered associative containers
  • https://en.cppreference.com/w/cpp/container

Contenery sekwencyjne:

std::vector

  • Array with a dynamic size, which is cache friendly.
  • In case of being full, it allocates bigger chunk of memory.
  • During reallocation, it reserves more memory than is needed.

vectors

template < class T, class Alloc = allocator > class vector; // generic template

std::vector<std::string> surnames; //or double.... or int :)
std::vector<double> v2(10); //ten elements (0)
std::vector<int> primes{2, 3, 5, 7, 11};

std::cout<< "Front: " << primes.front() << '\n'; // Front: 2
std::cout<< "Back:" << primes.back() << '\n'; // Back: 11
std::cout<<primes.size()<<std::endl; //5

template <typename ForwardIterator>
void displayRange(ForwardIterator first, ForwardIterator last)
{
    while(first!= last) {
        std::cout<< *first++ << ", ";
    }
}

std::vector<int>v1;
v1.assign(3,50); //50, 50, 50
v1.push_back(25);
//v1.assign({3});//if i give, this, will be only 3 in vector
v1.at(1) = 88; // Set element 1

•Public methods related to vector's capacity:

  • size
  • empty
  • capacity
  • reserve
  • shrink_to_fit
  • max_size

more: https://en.cppreference.com/w/cpp/container/vector

std::array

  • Fixed size array, which is cache friendly.
  • Zero-overhead in comparison to C-style array.
  • Strong typing.
  • Provides STL container interface.

  • How to access elements:

    • at / operator[]
    • front / back
    • data
    • Using iterators:
      • begin / cbegin
      • end / cend
      • rbegin/ crbegin
      • rend / crend
  • std::array::iterator is a random-access iterator

  • Public methods related to array's capacity:

    • size
    • empty
    • max_size
  • Other methods:

    • fill
    • swap
  • In case of arraywe can use comparison operators.

std::array<int, 5> numbers;
std::cout<< std::boolalpha;
std::cout<< "Isempty: " << numbers.empty() << '\n';
std::cout<< "Size: " << numbers.size() << '\n';
std::cout<< "Max size: " << numbers.max_size();

std::array<int, 3> a1 {1, 2, 3};
std::array<int, 3> a2 {3, 3, 3};
a1.swap(a2);
std::printf("a1\n");
displayArray(a1);
std::printf("a2\n");
displayArray(a2);

std::array<int, 3> numbers;
numbers.fill(7);

std::list

  • Doubly-linked list.
  • Random access is not supported.
  • Not cache friendly.
  • May lead to memory fragmentation.
  • Fast insert/remove operations.

  • How to access elements:

    • front / back
    • Using iterators:
      • begin / cbegin
      • end / cend
      • rbegin/ crbegin
      • rend / crend
  • std::list::iterator is a bidirectional iterator

  • How to modify list:

    • push_back/ push_front
    • pop_back/ pop_front
    • emplace_back/ emplace_front
    • insert / emplace
    • erase
    • clear
    • resize
    • swap
  • Special operations of std::list:

    • sort
    • merge
    • splice
    • reverse
    • unique
    • remove / remove_if
  std::list<int> l1; //l1.size()=0
  l1.push_back(3);
  l1.push_front(1);
  l1.insert(++l1.begin(), 2); //l1.begin()-iterator, żeby odczytać *l1.begin(), ++l1.begin()to już następne miejsce(...)l[0]++=>l[1]
  std::list<int> l2 {10, 11, 12, 13};
  l1.swap(l2); //różne długości , można
  l1.resize(2); //zmniejszenie do 2 elementów - obcięcie, jak więcej to 0
  l3.sort(); //sort jak niesortowana, std::string też
  l2.remove_if( [](int n) { return n==1; }); //usuń jedynki, lub n>10 usuń jak większe od 10...
  l4.unique(); //usuwa powtarzające się...unikalna lista

//ODWRÓCONA BO R jak reverse !!!!!!!!!!!!! rbegin
  for (auto ritr = l3.rbegin(); ritr != l3.rend(); ++ritr) { //operacja na iteratorach
      std::cout << *ritr << " "; //wypisuje od ostatniego
  }

Lista porozrzucane elementy w porównaniu do vectora, ale łatwiej dodać w środek element, bo w vectorze trzeba wszystko poprzesuwać (lista szybszy insert). Nie są w jednym bloku, może prowadzić do fragmentacji pamięci.

std::forward_list

W jednym kierunku przez co jest lżejsza. Jeżeli chcemy dużo usuwać i dodawać to lista, nie wektor. Jak dużo random access to vector.

  • How to access elements:
    • front
    • Using iterators:
      • begin / cbegin
      • end / cend
      • before_begin, cbefore_begin
  • std::forward_list::iterator is a forward iterator
  • How to modify forward_list:
    • push_front/ emplace_front/ pop_front
    • insert_after/ emplace_after
    • clear
    • erase_after
    • swap
    • resize
  • Special operations of forward_list:
    • sort
    • merge
    • reverse
    • splice_after
    • unique
    • remove / remove_if

std::deque

Kolejka z dwoma końcami. Jest fragmentacja pamięci. Jak chcemy tylko początek lub koniec to lepiej kolejka, jak dostęp do środka to może lista (decyzja).

  • Double-ended queue –often implemented asmany chunks of memory, which are allocated independently.
  • In case of being full, it reallocates memory.
  • Supports random access.
  • Fast insert/remove operations at the beginning/end.
  • How to access elements:
    • at / operator[]
    • front / back
    • Using iterators:
      • begin / cbegin
      • end / cend
      • rbegin/ crbegin
      • rend / crend
  • std::deque::iterator is a random-access iterator
  • Public methods related to deque's capacity:
    • size
    • empty
    • shrink_to_fit
    • max_size
  • In case of deque we can use comparison operators.
  • How to modify deque:
    • push_back/ pop_back
    • push_front/ pop_front
    • insert / emplace
    • emplace_front/ emplace_back
    • resize
    • swap
    • erase
    • clear
    std::deque<int> d1 {1, 4, 3, 1, 3, 2 };
    d1.pop_front();
    d1.pop_back();
    d1.push_front(9090);
    d1.push_back(32132);

    std::set<std::string> set;
    set.insert("Pan X");
    set.insert("Pani Y");
    set.insert("Pan X");

    for (auto s : set) {
        std::cout << s << " ";
    }

    d1.at(1) = 88; //drugi element (od 0) = 88
    std::cout<<data.at(0)<<"\n"; //jaki jest element 0

Associative containers available in STL:

  • Key-Value pairs, where key is unique.
  • Elements stored inside are sorted by key.
  • Usually implemented astree.
  • Complexity of search/insert/remove methods is logarithmic.

std::map

  • Key-Value pairs, where key is unique.
  • Elements stored inside are sorted by key.
  • Usually implemented as tree.
  • Complexity of search/insert/remove methods is logarithmic.

`map<int, char> map1; map1[1]='a';

std::multimap

  • Key-Value pairs
  • Elements stored inside are sorted by key.
  • Usually implemented astree.
  • Complexity of search/insert/remove methods is logarithmic.
  • How to access elements:
    • at / operator[] (only std::map)
    • Using iterators:
      • begin / cbegin
      • end / cend
      • rbegin/ crbegin
      • rend / crend
      • lower_bound/ upper_bound
      • equal_range
      • find
  • std::map::iterator and std::multimap::iterator are bidirectional iterators
  • Public methods related to map's capacity:
    • size
    • empty
    • max_size
    • count
  • In case of map we can use comparison operators.
  • How to modify map:
    • insert / emplace
    • emplace_hint
    • erase
    • swap
    • clear
std::map<std::string, int> myMap;
myMap[“Tommy”] = 21;

std::cout<< “Tommy’snumber:” << myMap[“Tommy”];


std::multimap<std::string, int> grades;

conststd::string studentName= “Tommy”;

grades.insert(std::make_pair(studentName, 5));
grades.insert(std::make_pair(studentName, 3));
grades.insert(std::make_pair(studentName, 4));

auto tommysGrades= grades.equal_range(studentName);

std::cout<< “Tommy’sgrades: “;
displayRange(tommysGrades.first, tommysGrades.second);

std::set

  • Contains unique values.
  • Elements stored inside are sorted.
  • Usually implemented astree.
  • The complexity of search/insert/remove is logarithmic.
  • Elements stored inside are sorted by value.
  • Usually implemented astree.
  • The complexity of search/insert/remove is logarithmic.

std::multiset

  • How to access elements: *Using iterators:
    • begin / cbegin
    • end / cend
    • rbegin/ crbegin
    • rend / crend
    • lower_bound/ upper_bound
    • equal_range
    • find
  • std::set::iterator and std::multiset::iterator are bidirectional iterators
  • Public methods related to set's capacity:
    • size
    • empty
    • max_size
    • count
  • In case of set we can use comparison operators.
  • How to modify set:
    • insert / emplace
    • emplace_hint
    • erase
    • swap
    • clear

Containers::unordered_associative

Unordered associative containers available in STL:

std::unordered_map

  • Key-Value pairs, where key is unique.
  • Hash table (uses hash function to transform key into an index).
  • Collision handling is needed.

std::unordered_multimap

  • Key-Value pairs.
  • Hash table (uses hash function to transform key into an index).
  • Collision handling is needed.

std::unordered_set

  • Uniquevalues.
  • Hash table (uses hash function to transform key into an index).
  • Collision handling is needed.

std::unordered_multiset

  • Hash table (uses hash function to transform key into an index).
  • Collision handling is needed.

Containers::adaptors

std::stack

  • Adapts container and provides LIFO (Last in –first out) interface.
  • Container type has to supports methods as:
    • push_back
    • pop_back
    • back
  • Methods:
    • top / pop
    • push / emplace
    • swap / empty / size

std::queue

  • Adapts container and provides FIFO (First in –first out) interface.
  • Container type has to supports methods as:
    • push_back
    • pop_front
    • back
    • front
  • Methods:
    • front / back
    • push / emplace / pop
    • swap / empty / size

std::priority_queue

  • Elements are prioritized according to comparator.
  • Container type has to supports methods as:
    • push_back
    • pop_back
    • back
  • Methods:
    • top
    • push / emplace / pop
    • swap / empty / size
⚠️ **GitHub.com Fallback** ⚠️