Sdílet prostřednictvím


Kontejnery standardní knihovny C++

Standardní knihovna poskytuje různé kontejnery bezpečného typu pro ukládání kolekcí souvisejících objektů. Kontejnery jsou šablony tříd. Když deklarujete proměnnou kontejneru, zadáte typ prvků, které bude kontejner obsahovat. Kontejnery lze vytvořit pomocí seznamů inicializátorů. Mají členské funkce pro přidávání a odebírání prvků a provádění dalších operací.

Iterace nad prvky v kontejneru a přístup k jednotlivým prvkům pomocí iterátorů. Iterátory můžete explicitně použít pomocí jejich členských funkcí a operátorů a globálních funkcí. Můžete je také použít implicitně, například pomocí smyčky range-for. Iterátory pro všechny kontejnery standardní knihovny C++ mají společné rozhraní, ale každý kontejner definuje vlastní specializované iterátory.

Kontejnery je možné rozdělit do tří kategorií: kontejnery sekvence, asociativní kontejnery a adaptéry kontejnerů.

Kontejnery sequence

Kontejnery sekvence udržují řazení vložených prvků, které zadáte.

Kontejner vector se chová jako pole, ale podle potřeby se může automaticky zvětšovat. Je to náhodný přístup a souvisle uložený a délka je vysoce flexibilní. Ztěchtoch vector Pokud pochybuje o tom, jaký druh kontejneru sekvence se má použít, začněte použitím vektoru! Další informace naleznete v tématu vector Třída.

Kontejner array má některé silné stránky vector, ale délka není tak flexibilní. Další informace naleznete v tématu array Třída.

Kontejner deque (fronta s dvojitým ukončením) umožňuje rychlé vkládání a odstraňování na začátku a na konci kontejneru. Sdílí výhody vectornáhodného přístupu a flexibilní délky , ale není souvislé. Další informace naleznete v tématu deque Třída.

list Kontejner je doubly propojený seznam, který umožňuje obousměrný přístup, rychlé vložení a rychlé odstranění kdekoli v kontejneru, ale nemůžete náhodně přistupovat k prvku v kontejneru. Další informace naleznete v tématu list Třída.

Kontejner forward_list je ingálně propojený seznam – verze listpředávání přístupu . Další informace naleznete v tématu forward_list Třída.

Asociativní kontejnery

V asociativních kontejnerech se prvky vloží do předdefinovaného pořadí – například vzestupně seřazené. K dispozici jsou také neseřazené asociativní kontejnery. Asociativní kontejnery je možné seskupit do dvou podmnožin: map a sad.

A map, někdy označovaný jako slovník, se skládá z páru klíč/hodnota. Klíč se používá k seřazení sekvence a hodnota je přidružená k housku. Například map může obsahovat klíče, které představují každé jedinečné slovo v textu a odpovídající hodnoty představující počet výskytů jednotlivých slov v textu. Neuspořádaná verze map je unordered_map. Další informace naleznete v tématu map Třída a unordered_map třída.

A set je pouze vzestupný kontejner jedinečných prvků – hodnota je také klíčem. Neuspořádaná verze set je unordered_set. Další informace naleznete v tématu set Třída a unordered_set třída.

set Umožňuje map vložit do kontejneru pouze jednu instanci klíče nebo elementu. Pokud je vyžadováno více instancí prvků, použijte multimap nebo multiset. Neuspořádané verze jsou unordered_multimap a unordered_multiset. Další informace naleznete v tématu multimap Třída, unordered_multimap Třída, multiset Třída a unordered_multiset Třída.

Seřazené mapy a sady podporují obousměrné iterátory a jejich neuspořádané protějšky podporují předávací iterátory. Další informace najdete v tématu Iterátory.

Heterogenní vyhledávání v asociativních kontejnerech (C++14)

Seřazené asociativní kontejnery (map, multimap, set a multiset) teď podporují heterogenní vyhledávání, což znamená, že už nepotřebujete předávat přesně stejný typ objektu jako klíč nebo prvek ve členských funkcích, jako find() je a lower_bound(). Místo toho můžete předat libovolný typ, pro který je definován přetížený operator< typ, který umožňuje porovnání s typem klíče.

Heterogenní vyhledávání je povoleno na základě výslovného souhlasu, když při deklarování proměnné kontejneru zadáte std::less<>std::greater<> srovnávací nebo kosočtvercový functor, jak je znázorněno zde:

std::set<BigObject, std::less<>> myNewSet;

Pokud použijete výchozí srovnávací program, kontejner se chová přesně stejně jako v jazyce C++11 a starším.

Následující příklad ukazuje, jak přetížit operator< uživatelům std::set vyhledávání jednoduše předáním malého řetězce, který lze porovnat s jednotlivými členy objektu BigObject::id .

#include <set>
#include <string>
#include <iostream>
#include <functional>

using namespace std;

class BigObject
{
public:
    string id;
    explicit BigObject(const string& s) : id(s) {}
    bool operator< (const BigObject& other) const
    {
        return this->id < other.id;
    }

    // Other members....
};

inline bool operator<(const string& otherId, const BigObject& obj)
{
    return otherId < obj.id;
}

inline bool operator<(const BigObject& obj, const string& otherId)
{
    return obj.id < otherId;
}

int main()
{
    // Use C++14 brace-init syntax to invoke BigObject(string).
    // The s suffix invokes string ctor. It is a C++14 user-defined
    // literal defined in <string>
    BigObject b1{ "42F"s };
    BigObject b2{ "52F"s };
    BigObject b3{ "62F"s };
    set<BigObject, less<>> myNewSet; // C++14
    myNewSet.insert(b1);
    myNewSet.insert(b2);
    myNewSet.insert(b3);
    auto it = myNewSet.find(string("62F"));
    if (it != myNewSet.end())
        cout << "myNewSet element = " << it->id << endl;
    else
        cout << "element not found " << endl;

    // Keep console open in debug mode:
    cout << endl << "Press Enter to exit.";
    string s;
    getline(cin, s);
    return 0;
}

//Output: myNewSet element = 62F

Následující členské funkce v mapách, multimapách, množině a více sadách byly přetíženy, aby podporovaly heterogenní vyhledávání:

  1. find

  2. count

  3. lower_bound

  4. upper_bound

  5. equal_range

Adaptéry kontejnerů

Adaptér kontejneru je varianta sekvence nebo asociativního kontejneru, který omezuje rozhraní pro jednoduchost a srozumitelnost. Adaptéry kontejnerů nepodporují iterátory.

Kontejner queue sleduje sémantiku FIFO (napřed in, first out). První vložený prvek – tedy vložený do fronty – je první, který se má rozbalit – to znamená, že se z fronty odebere. Další informace naleznete v tématu queue Třída.

Kontejner priority_queue je uspořádán tak, aby prvek, který má nejvyšší hodnotu, je vždy první ve frontě. Další informace naleznete v tématu priority_queue Třída.

Kontejner stack se řídí sémantikou LIFO (poslední in, first out). Poslední prvek nasdílený do zásobníku je první prvek, který se zapnul. Další informace naleznete v tématu stack Třída.

Protože adaptéry kontejnerů nepodporují iterátory, nelze je použít s algoritmy standardní knihovny C++. Další informace naleznete v tématu Algoritmy.

Požadavky na elementy kontejneru

Obecně platí, že prvky vložené do kontejneru standardní knihovny jazyka C++ můžou být přibližně libovolného typu objektu, pokud jsou kopírovatelné. Pohyblivé prvky – například ty vector<unique_ptr<T>> , které jsou vytvořené pomocí použití unique_ptr<> , budou fungovat, pokud nevoláte členské funkce, které se je pokusí zkopírovat.

Destruktor nemůže vyvolat výjimku.

Seřazené asociativní kontejnery popsané výše v tomto článku musí mít definovaný operátor veřejného porovnání. Ve výchozím nastavení je operator<operátor , ale i typy, se operator< kterými nefungují, se podporují.

Některé operace s kontejnery můžou také vyžadovat veřejný výchozí konstruktor a operátor veřejné ekvivalence. Například neseřazené asociativní kontejnery vyžadují podporu rovnosti a hashování.

Přístup k elementům kontejneru

K prvkům kontejnerů se přistupuje pomocí iterátorů. Další informace najdete v tématu Iterátory.

Poznámka:

Smyčky založené na rozsahu můžete také použít k iteraci kolekcí standardní knihovny C++.

Porovnání kontejnerů

Všechny kontejnery přetíží operátor== pro porovnání dvou kontejnerů stejného typu, které mají stejný typ prvku. Pomocí == můžete porovnat vektorový<řetězec> s jiným<vektorovým řetězcem>, ale nemůžete ho použít k porovnání vektorového<řetězce> se seznamovým<řetězcem> nebo vektorovým řetězcem> s vektorovým<<znakem*>. V jazyce C++98/03 můžete použít std::equal nebo std::mismatch porovnat odlišné typy kontejnerů nebo typy prvků. V jazyce C++11 můžete použít std::is_permutationtaké . Ve všech těchto případech ale funkce předpokládají, že kontejnery mají stejnou délku. Pokud je druhá oblast kratší než první, pak výsledky nedefinovaného chování. Pokud je druhá oblast delší, výsledky můžou být stále nesprávné, protože porovnání nikdy nepřetrvá po konci prvního rozsahu.

Porovnání rozdílných kontejnerů (C++14)

V jazyce C++14 a novějších můžete porovnávat odlišné kontejnery a/nebo odlišné typy prvků pomocí jednoho z std::equalstd::mismatchpřetížených funkcí nebo std::is_permutation přetížení funkcí, které přebírají dva úplné rozsahy. Tato přetížení umožňují porovnat kontejnery s různými délkami. Tato přetížení jsou mnohem méně náchylná k chybě uživatele a jsou optimalizovaná tak, aby při porovnávání kontejnerů s rozdílovými délkami vrátila hodnotu false v konstantním čase. Proto doporučujeme použít tato přetížení, pokud nemáte jasný důvod, proč ne, nebo používáte std::list kontejner, který nemá prospěch z optimalizací duálního rozsahu.

Viz také

Paralelní kontejnery
<sample container>
Bezpečný přístup z více vláken ve standardní knihovně C++