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 vector
ná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 list
př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í:
find
count
lower_bound
upper_bound
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_permutation
také . 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::equal
std::mismatch
př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++