Kontejnery standardní knihovny C++

Standardní knihovna poskytuje různé typové kontejnery pro ukládání kolekcí souvisejících objektů. Kontejnery jsou šablony tříd. Když deklarujete proměnnou kontejneru, zadáte typ elementů, 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í.

Budete iterovat prvky v kontejneru a přistupovat k jednotlivým prvkům pomocí iterátorů. Iterátory můžete použít explicitně pomocí jejich členských funkcí, 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 lze rozdělit do tří kategorií: kontejnery sekvencování, asociativní kontejnery a adaptéry kontejnerů.

Kontejnery sekvence

Kontejnery sekvence udržují pořadí vkládaných prvků, které zadáte.

Kontejner vector se chová jako pole, ale může se automaticky zvětšovat podle potřeby. Jedná se o náhodný přístup a souvisle uložený a jeho délka je velmi flexibilní. Z těchto a dalších důvodů vector je upřednostňovaným kontejnerem sekvence pro většinu aplikací. Pokud máte pochybnosti o tom, jaký druh kontejneru sekvence použít, začněte vektorem. Další informace najdete v tématu Třída.

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

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

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

Kontejner forward_list je přehledně propojený seznam – verze pro dopředný přístup list . Další informace najdete v tématu Třída.

Asociativní kontejnery

V asociativních kontejnerech jsou prvky vloženy v předdefinované pořadí – například jako seřazené vzestupně. K dispozici jsou také neuspořádané asociativní kontejnery. Asociativní kontejnery lze seskupit do dvou podmnožiny: mapy a sady.

, map který se někdy označuje jako slovník, se skládá z páru klíč/hodnota. Klíč se používá k řazení sekvence a hodnota je přidružena k tomuto klíči. Například může obsahovat klíče, které představují každé jedinečné slovo v textu a odpovídající hodnoty, které představují počet, kolikrát se každé slovo map v textu zobrazí. Neuspořádané verze map je unordered_map . Další informace najdete v tématu Třída a 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 najdete v tématu Třída a Třída.

I umožňují vložit do kontejneru pouze jednu instanci klíče nebo mapset elementu. Pokud je vyžadováno více instancí elementů, použijte multimap nebo multiset . Neuspořádané verze jsou a unordered_multimapunordered_multiset . Další informace najdete v tématu Třída, Třída, Třídaa Třída.

Seřazené mapy a sady podporují obousměrné iterátory a jejich neuspořádané protějšky podporují dopředné 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ž není nutné předávat přesně stejný typ objektu jako klíč nebo prvek v členských funkcích, jako je a find()lower_bound() . Místo toho můžete předat libovolný typ, pro který je definováno přetížené, které umožňuje operator< porovnání s typem klíče.

Heterogenní vyhledávání se povolí výslovně, když při deklaraci proměnné kontejneru zadáte komparátor nebo "kosočtverec", jak je znázorněno std::less<>std::greater<> zde:

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

Pokud použijete výchozí komparátor, bude se kontejner chovat stejně jako v jazyce C++11 a starším.

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

#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, multimap, set a multiset byly přetíženy pro podporu heterogenního vyhledávání:

  1. find

  2. count

  3. lower_bound

  4. upper_bound

  5. equal_range

Adaptéry kontejneru

Adaptér kontejneru je variací sekvence nebo asociativního kontejneru, který z důvodu jednoduchosti a přehlednosti omezuje rozhraní. Adaptéry kontejnerů nepodporují iterátory.

Kontejner queue se řídí sémantikou FIFO (first in, first out). První prvek push (vložení do fronty) je prvním prvkem, který se má vyjmout – to znamená, že se odebere z fronty. Další informace najdete v tématu Třída.

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

Kontejner stack se řídí sémantikou LIFO (poslední in, první ven). Posledním prvkem nasunutým do zásobníku je první prvek, který se přehodil. Další informace najdete v tématu Třída.

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

Požadavky na elementy kontejneru

Obecně platí, že prvky vložené do kontejneru standardní knihovny C++ mohou mít libovolný typ objektu, pokud se kopírují. Pouze vyměnitelné prvky – například prvky, které jsou vytvořeny pomocí , budou fungovat, pokud nevoláte členské funkce, které se je vector<unique_ptr<T>>unique_ptr<> pokoušejí zkopírovat.

Destruktor nemůže vyvolat výjimku.

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

Některé operace s kontejnery mohou také vyžadovat veřejný výchozí konstruktor a operátor veřejné ekvivalence. Například neuspořádané 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 for založené na rozsahu můžete použít také k iteraci v kolekcích standardní knihovny C++.

Porovnání kontejnerů

Všechny kontejnery přetěžují operátor== pro porovnání dvou kontejnerů stejného typu, které mají stejný typ elementu. Pomocí == můžete porovnat vektorový řetězec s jiným vektorovým řetězcem , ale nemůžete ho použít k porovnání řetězce vektoru s řetězcem seznamu nebo vektorového řetězce <>< s ><><><>< vektorovým znakem*. > V jazyce C++98/03 můžete použít nebo k porovnání různých typů kontejnerů std::equalstd::mismatch a/nebo typů elementů. V jazyce C++11 můžete také použít std::is_permutation . Ve všech těchto případech ale funkce předpokládají, že kontejnery mají stejnou délku. Pokud je druhý rozsah kratší než první, pak nedefinované výsledky chování. Pokud je druhý rozsah delší, mohou být výsledky stále nesprávné, protože porovnání nikdy nepotrvá za koncem prvního rozsahu.

Porovnání odlišných kontejnerů (C++14)

V jazyce C++14 a novějším můžete porovnat odlišné kontejnery nebo odlišné typy elementů pomocí jednoho z přetížení funkce , nebo , které převezměte dva úplné std::equalstd::mismatchstd::is_permutation 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ání kontejnerů s odlišnými délkami v konstantním čase vracela hodnotu false. Proto doporučujeme použít tato přetížení, pokud nemáte jasný důvod, proč to ne, nebo pokud používáte kontejner, který nevyužít optimalizace s duálním std::list rozsahem.

Viz také

Paralelní kontejnery
<sample container>
Bezpečnost vlákna ve standardní knihovně C++