Udostępnij za pośrednictwem


Kontenery standardowej biblioteki C++

Biblioteka Standardowa udostępnia różne kontenery bezpieczne dla typów do przechowywania kolekcji powiązanych obiektów. Kontenery to szablony klas. Podczas deklarowania zmiennej kontenera należy określić typ elementów, które będą przechowywane w kontenerze. Kontenery można tworzyć z listami inicjatorów. Mają one funkcje składowe do dodawania i usuwania elementów oraz wykonywania innych operacji.

Iteracja elementów w kontenerze i uzyskiwanie dostępu do poszczególnych elementów przy użyciu iteratorów. Iteratory można jawnie używać przy użyciu ich funkcji składowych i operatorów oraz funkcji globalnych. Można ich również używać niejawnie, na przykład za pomocą pętli range-for. Iteratory dla wszystkich kontenerów biblioteki standardowej języka C++ mają wspólny interfejs, ale każdy kontener definiuje własne wyspecjalizowane iteratory.

Kontenery można podzielić na trzy kategorie: kontenery sekwencji, kontenery kojarzące i karty kontenerów.

Kontenery sekwencji

Kontenery sekwencji zachowują kolejność wstawionych elementów, które określisz.

Kontener zachowuje się jak tablica vector , ale może automatycznie rosnąć zgodnie z potrzebami. Jest to dostęp losowy i stale przechowywany, a długość jest wysoce elastyczna. Z tych powodów i nie tylko vector jest preferowanym kontenerem sekwencji dla większości aplikacji. W razie wątpliwości co do rodzaju kontenera sekwencji do użycia, zacznij od użycia wektora! Aby uzyskać więcej informacji, zobacz vector Klasa.

Kontener array ma pewne mocne strony vector, ale długość nie jest tak elastyczna. Aby uzyskać więcej informacji, zobacz array Klasa.

deque Kontener (kolejka podwójna) umożliwia szybkie wstawianie i usuwanie na początku i na końcu kontenera. Udostępnia ona losowe i elastyczne zalety programu vector, ale nie jest ciągłe. Aby uzyskać więcej informacji, zobacz deque Klasa.

list Kontener to podwójnie połączona lista, która umożliwia dostęp dwukierunkowy, szybkie wstawianie i szybkie usuwanie w dowolnym miejscu w kontenerze, ale nie można losowo uzyskać dostępu do elementu w kontenerze. Aby uzyskać więcej informacji, zobacz list Klasa.

forward_list Kontener jest listą połączoną ze singly — wersją dostępu do przodu programu list. Aby uzyskać więcej informacji, zobacz forward_list Klasa.

Kontenery asocjacyjne

W kontenerach asocjacyjnych elementy są wstawiane wstępnie zdefiniowanej kolejności — na przykład jako posortowane rosnąco. Dostępne są również nieurządzane kontenery asocjacyjne. Kontenery asocjacyjne można zgrupować w dwa podzestawy: mapy i zestawy.

Element map, czasami nazywany słownikiem, składa się z pary klucz/wartość. Klucz jest używany do zamawiania sekwencji, a wartość jest skojarzona z tym kluczem. Na przykład element map może zawierać klucze reprezentujące każde unikatowe słowo w tekście i odpowiadające im wartości reprezentujące liczbę wystąpień każdego wyrazu w tekście. Nieurządkowana wersja elementu map to unordered_map. Aby uzyskać więcej informacji, zobacz map Class and Class (Klasa i unordered_map klasa).

A set to tylko rosnący kontener unikatowych elementów — wartość jest również kluczem. Nieurządkowana wersja elementu set to unordered_set. Aby uzyskać więcej informacji, zobacz set Class and Class (Klasa i unordered_set klasa).

Oba map elementy i set zezwalają tylko na wstawianie jednego wystąpienia klucza lub elementu do kontenera. Jeśli wymagane jest wiele wystąpień elementów, użyj polecenia multimap lub multiset. Nieurządkowane wersje to unordered_multimap i unordered_multiset. Aby uzyskać więcej informacji, zobacz multimap Klasa, unordered_multimap Klasa, multiset Klasa i unordered_multiset Klasa.

Uporządkowane mapy i zestawy obsługują iteratory dwukierunkowe, a ich nieuordowane odpowiedniki obsługują iteratory przesyłania dalej. Aby uzyskać więcej informacji, zobacz Iteratory.

Heterogeniczne wyszukiwanie w kontenerach asocjacyjnych (C++14)

Uporządkowane kontenery asocjacyjne (mapowanie, multimapa, zestaw i multiset) obsługują teraz heterogeniczne wyszukiwanie, co oznacza, że nie trzeba już przekazywać dokładnie tego samego typu obiektu co klucz lub element w funkcjach składowych, takich jak find() i lower_bound(). Zamiast tego można przekazać dowolny typ, dla którego zdefiniowano przeciążony operator< element, który umożliwia porównanie z typem klucza.

Wyszukiwanie heterogeniczne jest włączone na zasadzie zgody podczas określania std::less<> komparatora lub std::greater<> "functor diamentu" podczas deklarowania zmiennej kontenera, jak pokazano poniżej:

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

Jeśli używasz domyślnego komparatora, kontener zachowuje się dokładnie tak samo jak w języku C++11 i starszych wersjach.

W poniższym przykładzie pokazano, jak przeciążyć operator< , aby umożliwić użytkownikom std::set wyszukiwanie, po prostu przekazując mały ciąg, który można porównać z elementem członkowskim każdego obiektu 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

Następujące funkcje składowe w mapie, wielomapie, zestawie i wielozestawie zostały przeciążone w celu obsługi wyszukiwania heterogenicznego:

  1. find

  2. count

  3. lower_bound

  4. upper_bound

  5. equal_range

Adaptery kontenerów

Adapter kontenera to odmiana sekwencji lub kontenera kojarzącego, który ogranicza interfejs dla uproszczenia i jasności. Karty kontenerów nie obsługują iteratorów.

queue Kontener jest zgodny z semantyką FIFO (najpierw w pierwszej kolejności). Pierwszy element wypchnięty — czyli wstawiony do kolejki — jest pierwszym elementem, który ma zostać zwinięty — czyli usuniętym z kolejki. Aby uzyskać więcej informacji, zobacz queue Klasa.

priority_queue Kontener jest zorganizowany tak, aby element, który ma najwyższą wartość, zawsze był pierwszy w kolejce. Aby uzyskać więcej informacji, zobacz priority_queue Klasa.

stack Kontener jest zgodny z semantykami LIFO (ostatni w, pierwszy na wyjęcie). Ostatnim elementem wypchniętym na stos jest pierwszy element zwinięty. Aby uzyskać więcej informacji, zobacz stack Klasa.

Ponieważ karty kontenerów nie obsługują iteratorów, nie mogą być używane z algorytmami biblioteki standardowej języka C++. Aby uzyskać więcej informacji, zobacz Algorytmy.

Wymagania dotyczące elementów kontenera

Ogólnie rzecz biorąc, elementy wstawione do kontenera biblioteki standardowej języka C++ mogą być niemal dowolnym typem obiektu, jeśli można je skopiować. Elementy tylko wymienne — na przykład te, które vector<unique_ptr<T>> są tworzone przy użyciu, unique_ptr<> będą działać tak długo, jak nie wywołujesz funkcji składowych, które próbują je skopiować.

Destruktor nie może zgłosić wyjątku.

Uporządkowane kontenery asocjacyjne — opisane wcześniej w tym artykule — muszą mieć zdefiniowany operator porównania publicznego. Domyślnie operator to operator<, ale obsługiwane są nawet typy, z którymi nie działają operator< .

Niektóre operacje na kontenerach mogą również wymagać publicznego konstruktora domyślnego i publicznego operatora równoważności. Na przykład kontenery asocjacyjne nieurządzane wymagają obsługi równości i tworzenia skrótów.

Uzyskiwanie dostępu do elementów kontenera

Dostęp do elementów kontenerów jest uzyskiwany przy użyciu iteratorów. Aby uzyskać więcej informacji, zobacz Iteratory.

Uwaga

Można również używać pętli opartych na zakresie do iterowania kolekcji biblioteki standardowej języka C++.

Porównywanie kontenerów

Wszystkie kontenery przeciążą operator== do porównywania dwóch kontenerów tego samego typu, które mają ten sam typ elementu. Można użyć == do porównania ciągu wektorowego z innym ciągiem> wektorowym<, ale nie można go użyć do porównania ciągu> wektorowego<<z ciągiem> listy<lub ciągiem> wektorowym<<*>.> W języku C++98/03 można użyć std::equal polecenia lub std::mismatch porównać różne typy kontenerów i/lub typów elementów. W języku C++11 można również użyć polecenia std::is_permutation. Jednak we wszystkich tych przypadkach funkcje zakładają, że kontenery mają taką samą długość. Jeśli drugi zakres jest krótszy niż pierwszy, wyniki zachowania niezdefiniowanego. Jeśli drugi zakres jest dłuższy, wyniki mogą być nadal nieprawidłowe, ponieważ porównanie nigdy nie będzie kontynuowane poza końcem pierwszego zakresu.

Porównywanie niepodobnych kontenerów (C++14)

W języku C++14 lub nowszym można porównać różne kontenery i/lub różne typy elementów przy użyciu jednego z std::equalprzeciążeń funkcji , std::mismatchlub std::is_permutation funkcji, które przyjmują dwa kompletne zakresy. Te przeciążenia umożliwiają porównywanie kontenerów o różnych długościach. Te przeciążenia są znacznie mniej podatne na błędy użytkownika i są zoptymalizowane pod kątem zwracania wartości false w stałym czasie, gdy kontenery o różnej długości są porównywane. W związku z tym zalecamy użycie tych przeciążeń, chyba że masz wyraźny powód, aby nie lub używasz kontenera, który nie korzysta z optymalizacji z podwójnym zakresem std::list .

Zobacz też

Kontenery równoległe
<sample container>
Bezpieczeństwo wątku w standardowej bibliotece C++