| Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente |
| lang:cpp:container [2020/04/06 15:46] – [Spécificités] : fix std::vector root | lang:cpp:container [2025/06/30 11:40] (Version actuelle) – [Template] : distinction entre map et unordered_map root |
|---|
| ====Spécificités==== | =====Spécificités===== |
| ===Différence entre les conteneurs=== | ====Différence entre les conteneurs==== |
| ^Conteneur ^ Mémoire contiguë ^ | ^Conteneur ^ Mémoire contiguë ^ |
| | vector | Oui | | | vector | Oui | |
| [[https://embeddedartistry.com/blog/2017/09/11/choosing-the-right-container-sequential-containers/|Choosing the Right Container: Sequential Containers]] {{ :lang:cpp:container:choosing_the_right_container_sequential_containers_embedded_artistry_2019-11-13_11_44_12_.html |Archive du 09/09/2019 le 13/11/2019}} | [[https://embeddedartistry.com/blog/2017/09/11/choosing-the-right-container-sequential-containers/|Choosing the Right Container: Sequential Containers]] {{ :lang:cpp:container:choosing_the_right_container_sequential_containers_embedded_artistry_2019-11-13_11_44_12_.html |Archive du 09/09/2019 le 13/11/2019}} |
| |
| ===std::set=== | ====std::set==== |
| Les itérateurs ''begin'' et ''end'' renvoient un type ''const''. ''std::set'' est ordonné et sa clé est stockée dans un arbre de type red-black. | Les itérateurs ''begin'' et ''end'' renvoient un type ''const''. ''std::set'' est ordonné et sa clé est stockée dans un arbre de type red-black. |
| |
| [[https://stackoverflow.com/questions/2217878/c-stdset-update-is-tedious-i-cant-change-an-element-in-place|C++ std::set update is tedious: I can't change an element in place]] {{ :lang:cpp:container:stl_-_c_std_set_update_is_tedious_i_can_t_change_an_element_in_place_-_stack_overflow_2020-01-02_07_50_36_.html |Archive du 07/02/2010 le 02/01/2020}} | [[https://stackoverflow.com/questions/2217878/c-stdset-update-is-tedious-i-cant-change-an-element-in-place|C++ std::set update is tedious: I can't change an element in place]] {{ :lang:cpp:container:stl_-_c_std_set_update_is_tedious_i_can_t_change_an_element_in_place_-_stack_overflow_2020-01-02_07_50_36_.html |Archive du 07/02/2010 le 02/01/2020}} |
| |
| ===set::vector=== | ====set::vector==== |
| |
| Il y a un cas particulier pour ''std::vector<bool>''. La mémoire est optimisée donc un octet peut stocker 8 bits. Ce qui fait que l'accès à la propriété ''data()'' est bloquée. Si cette optimisation n'est pas souhaitée, il faut utiliser un ''std::vector<unsigned char>''. | Il y a un cas particulier pour ''std::vector<bool>''. La mémoire est optimisée donc un octet peut stocker 8 bits. Ce qui fait que l'accès à la propriété ''data()'' est bloquée. Si cette optimisation n'est pas souhaitée, il faut utiliser un ''std::vector<unsigned char>''. |
| |
| ====Manipulation des données==== | =====Autres implémentations===== |
| ===std::string et std::array=== | |
| | Map et set : https://github.com/martinus/unordered_dense. Tout est stocké dans un ''std::vector''. |
| | |
| | =====Manipulation des données===== |
| | ====std::array==== |
| * ''std::array'' to ''std::string'' | * ''std::array'' to ''std::string'' |
| <code cpp> | <code cpp> |
| </code> | </code> |
| |
| ===Comparaison de containers=== | =====Interopérabilité===== |
| | ====Comparaison de containers==== |
| <code cpp> | <code cpp> |
| #include <utility> | #include <utility> |
| bool v1smaller = std::lexicographical_compare(v1.begin(), v1.begin(), s2.begin(), s2.end()); | bool v1smaller = std::lexicographical_compare(v1.begin(), v1.begin(), s2.begin(), s2.end()); |
| </code> | </code> |
| | |
| | ====Template==== |
| | |
| | * D'un container valeur |
| | |
| | <code cpp> |
| | template <template <typename, typename...> class Container, typename T, typename... Args> |
| | void function(const Container<T, Args...>& container); |
| | </code> |
| | |
| | * D'un container clé / valeur |
| | |
| | <code cpp> |
| | template <template <typename, typename, typename...> class Map, typename Key, typename Value, typename... Args> |
| | void function(const Map<Key, Value, Args...>& container); |
| | </code> |
| | |
| | Attention, dans ''Args'', il y a ''%%std::allocator<std::pair<const Key, Value>>%%''. Il n'est pas possible de définir une map en inversant simplement les clés / valeurs avec la définition précédente. |
| | |
| | Il faut utiliser la version complète: |
| | |
| | <code cpp> |
| | template <typename T, typename U, template <typename> typename Hash, |
| | template <typename> typename CompareTemplate, |
| | template <typename> typename AllocatorTemplate, |
| | template <typename, typename, typename, typename, typename> typename Container> |
| | Container<U, T, Hash<U>, CompareTemplate<U>, AllocatorTemplate<std::pair<const U, T>>> invertUnorderedMap( |
| | const Container<T, U, Hash<T>, CompareTemplate<T>, AllocatorTemplate<std::pair<const T, U>>> |
| | &unordered_map) |
| | |
| | template <typename T, typename U, template <typename> typename CompareTemplate, |
| | template <typename> typename AllocatorTemplate, |
| | template <typename, typename, typename, typename> typename Container> |
| | Container<U, T, CompareTemplate<U>, AllocatorTemplate<std::pair<const U, T>>> invertMap( |
| | const Container<T, U, CompareTemplate<T>, AllocatorTemplate<std::pair<const T, U>>> &map) |
| | </code> |
| | =====Spécificités===== |
| | ====std::vector==== |
| | |
| | * Constructeur taille / valeur |
| | |
| | Ne pas utiliser le constructeur avec ''{}'' si on souhaite utiliser celui ''(taille, valeur_par_defaut)''. |
| | |
| | Ou sinon, il faut expliciter tout le constructeur sans passer par les valeurs par défaut : ''{15,0,std::allocator<int>()}''. Ainsi, il comprendra qu'il faut utiliser le constructeur et non l'initialisation par liste. |
| | |
| | [[https://stackoverflow.com/questions/53541937/allocate-vector-size-with-list-initialization-curly-braces|Allocate vector size with list initialization (curly braces)]] {{ :lang:cpp:container:c_-_allocate_vector_size_with_list_initialization_curly_braces_-_stack_overflow_23_12_2022_09_55_33_.html |Archive du 29/11/2018 le 23/12/2022}} |
| | |
| | ====Héritage==== |
| | |
| | Il n'est pas possible de faire un conteneur pour une classe de base. Il faut alors stocker uniquement le pointeur (intelligent ou brut). |
| | |
| | <code cpp> |
| | #include <iostream> |
| | #include <memory> |
| | #include <vector> |
| | |
| | class Base { |
| | public: |
| | virtual void identify() { std::cout << "BASE\n"; } |
| | }; |
| | |
| | class Derived : public Base { |
| | public: |
| | virtual void identify() { std::cout << "DERIVED\n"; } |
| | }; |
| | |
| | int main() { |
| | std::vector<std::unique_ptr<Base>> vect; |
| | vect.push_back(std::make_unique<Derived>()); |
| | |
| | vect[0]->identify(); |
| | return 0; |
| | } |
| | </code> |
| | |
| | [[https://stackoverflow.com/questions/8777724/store-derived-class-objects-in-base-class-variables|Store derived class objects in base class variables]] {{ :lang:cpp:container:c_-_store_derived_class_objects_in_base_class_variables_-_stack_overflow_27_02_2023_14_24_46_.html |Archive du 08/01/2012 le 27/02/2023}} |