C++ benannte Anforderungen: SequenceContainer
Von cppreference.com
< cpp | benannte req
Ein SequenceContainer ist ein Container, der Objekte desselben Typs in einer linearen Anordnung speichert.
Inhalt |
[bearbeiten] Anforderungen
Gegeben seien folgende Typen und Werte
| Typ | Definition |
C
|
eine Sequenzcontainer-Klasse |
T
|
der Elementtyp von C |
A
|
der Allokator-Typ von C
|
R (seit C++23) |
ein Typ, der container-compatible-range <T> modelliert |
Args (seit C++11) |
ein Template-Parameterpaket |
Iter
|
C::iterator
|
Ref
|
C::reference
|
CRef
|
C::const_reference
|
| Wert | Definition |
| v | ein Wert vom Typ C |
| cv | ein Wert vom Typ const C |
| i, j | LegacyInputIteratoren, so dass [i, j) ein gültiger Bereich ist und die Iteratoren auf Elemente verweisen, die implizit in C::value_type konvertierbar sind |
| rg (seit C++23) | ein Wert vom Typ R |
| il (seit C++11) | ein Wert vom Typ std::initializer_list<C::value_type> |
| n | ein Wert vom Typ C::size_type |
| p | ein gültiger const Iterator in v |
| q | ein gültiger dereferenzierbarer const Iterator in v |
| q1, q2 | const Iteratoren in v, so dass [q1, q2) ein gültiger Bereich ist |
| t | ein Wert(bis C++11)ein lvalue oder const rvalue(seit C++11) vom Typ C::value_type |
| rv (seit C++11) | ein nicht-const rvalue vom Typ C::value_type |
| args (seit C++11) | ein Funktionsparameterpaket mit dem Muster Arg&& |
C erfüllt die Anforderungen von SequenceContainer, wenn alle folgenden Bedingungen erfüllt sind
-
Cerfüllt die Anforderungen von Container. - Die folgenden Anweisungen und Ausdrücke sind wohlgeformt und haben die spezifizierte Semantik
| Grundlegende Operationen (erforderlich für alle Sequenzcontainer in der Standardbibliothek außer std::array(seit C++11)) | |||
|---|---|---|---|
| Anweisung | Semantik[1] | ||
| C c(n, t); | Auswirkung | Konstruiert den Sequenzcontainer, der n Kopien von t enthält. | |
| Vorbedingung |
| ||
| Nachbedingung | std::distance(c.begin(), c.end()) ist n. | ||
| C c(i, j); | Auswirkung | Konstruiert den Sequenzcontainer, der elementweise gleich dem Bereich [i, j) ist.
| |
| Vorbedingung |
| ||
| Nachbedingung | std::distance(c.begin(), c.end()) ist std::distance(i, j). | ||
| Ausdruck | Typ | Semantik | |
| C(std::from_range, rg) (seit C++23) |
C
|
Auswirkung | Konstruiert den Sequenzcontainer, der elementweise gleich dem Bereich rg ist.
|
| Vorbedingung | T ist EmplaceConstructible in C aus *ranges::begin(rg). | ||
| Nachbedingung | std::distance(begin(), end()) ist ranges::distance(rg). | ||
| C(il) (seit C++11) |
C
|
Entspricht C(il.begin(), il.end()). | |
| v = il (seit C++11) |
C&
|
Auswirkung | Weist den von il repräsentierten Bereich v zu.[2] |
| Rückgabewert | *this | ||
| Vorbedingung | T ist CopyInsertable in C und CopyAssignable. | ||
| Nachbedingung | Bestehende Elemente von v werden entweder zerstört oder zugewiesen. | ||
| v.emplace(p, args) (seit C++11) |
Iter
|
Auswirkung | Fügt ein Objekt vom Typ T, konstruiert mit std::forward<Args>(args)..., vor p ein. |
| Rückgabewert | Ein Iterator, der auf das neue Element zeigt, das aus args in v konstruiert wurde. | ||
| Vorbedingung | T ist EmplaceConstructible in C aus args. | ||
| v.insert(p, t) | Iter
|
Auswirkung | Fügt eine Kopie von t vor p ein. |
| Rückgabewert | Ein Iterator, der auf die Kopie von t zeigt, die in v eingefügt wurde. | ||
| Vorbedingung |
| ||
| v.insert(p, rv) (seit C++11) |
Iter
|
Auswirkung | Fügt eine Kopie von rv vor p ein, möglicherweise unter Verwendung von Move-Semantik. |
| Rückgabewert | Ein Iterator, der auf die Kopie von rv zeigt, die in v eingefügt wurde. | ||
| Vorbedingung | T ist MoveInsertable in C. | ||
| v.insert(p, n, t) | Iter
|
Auswirkung | Fügt n Kopien von t vor p ein. |
| Rückgabewert | Ein Iterator, der auf die Kopie des ersten in v eingefügten Elements zeigt, oder p, wenn n 0 ist. | ||
| Vorbedingung |
| ||
| v.insert(p, i, j) | Iter
|
Auswirkung | Fügt Kopien von Elementen im Bereich [i, j) vor p ein.
|
| Rückgabewert | Ein Iterator, der auf die Kopie des ersten in v eingefügten Elements zeigt, oder p, wenn i == j true ist. | ||
| Vorbedingung |
| ||
| v.insert_range(p, rg) (seit C++23) |
Iter
|
Auswirkung | Fügt Kopien von Elementen in rg vor p ein.
|
| Rückgabewert | Ein Iterator, der auf die Kopie des ersten in v eingefügten Elements zeigt, oder p, wenn rg leer ist. | ||
| Vorbedingung |
| ||
| v.insert(p, il) (seit C++11) |
Iter
|
Entspricht v.insert(p, il.begin(), il.end()). | |
| v.erase(q) | Iter
|
Auswirkung | Löscht das von q referenzierte Element. |
| Rückgabewert | Ein Iterator, der auf das Element zeigt, das unmittelbar auf q folgt, bevor das Element gelöscht wird, oder v.end(), wenn kein solches Element existiert. | ||
| v.erase(q1, q2) | Iter
|
Auswirkung | Löscht Elemente im Bereich [q1, q2). |
| Rückgabewert | Ein Iterator, der auf das Element zeigt, auf das q2 vor dem Löschen von Elementen gezeigt hat, oder v.end(), wenn kein solches Element existiert. | ||
| v.clear() | void | Auswirkung | Zerstört alle Elemente in v.
|
| Nachbedingung | v.empty() ist true. | ||
| Komplexität | Linear. | ||
| v.assign(i, j) | void | Auswirkung | Ersetzt Elemente in v durch eine Kopie von [i, j).
|
| Vorbedingung |
| ||
| v.assign_range(rg) (seit C++23) |
void | Auswirkung | Ersetzt Elemente in v durch eine Kopie jedes Elements in rg.
|
| Vorbedingung |
| ||
| v.assign(il) (seit C++11) |
void | Entspricht v.assign(il.begin(), il.end()). | |
| v.assign(n, t) | void | Auswirkung | Ersetzt Elemente in v durch n Kopien von t. |
| Vorbedingung |
| ||
| Zusätzliche Operationen[3] (nur für angegebene Sequenzcontainer erforderlich, ohne std::)
| |||
| Ausdruck | Typ | Semantik | |
| v.front() | Ref
|
Container | basic_string, array, vector, inplace_vector, deque, list, forward_list
|
| Rückgabewert | *v.begin() | ||
| cv.front() | CRef
|
Container | basic_string, array, vector, inplace_vector, deque, list, forward_list
|
| Rückgabewert | *cv.begin() | ||
| v.back() | Ref
|
Container | basic_string, array, vector, inplace_vector, deque, list
|
| Entspricht auto tmp = v.end(); --tmp; return *tmp;[4]. | |||
| cv.back() | CRef
|
Container | basic_string, array, vector, inplace_vector, deque, list
|
| Entspricht auto tmp = cv.end(); --tmp; return *tmp;[5]. | |||
| v.emplace_front(args) (seit C++11) |
void | Container | deque, list, forward_list
|
| Auswirkung | Setzt ein Objekt vom Typ T, konstruiert mit std::forward<Args>(args)..., am Anfang ein. | ||
| Rückgabewert | v.front() | ||
| Vorbedingung | T ist EmplaceConstructible in C aus args. | ||
| v.emplace_back(args) (seit C++11) |
void | Container | vector, inplace_vector, deque, list
|
| Auswirkung | Hängt ein Objekt vom Typ T an, konstruiert mit std::forward<Args>(args).... | ||
| Rückgabewert | v.back() | ||
| Vorbedingung | T ist EmplaceConstructible in C aus args. | ||
| v.push_front(t) | void | Container | deque, list, forward_list
|
| Auswirkung | Fügt eine Kopie von t am Anfang ein. | ||
| Vorbedingung |
| ||
| v.push_front(rv) (seit C++11) |
void | Container | deque, list, forward_list
|
| Auswirkung | Fügt eine Kopie von rv am Anfang ein, möglicherweise unter Verwendung von Move-Semantik. | ||
| Vorbedingung | T ist MoveInsertable in C. | ||
| v.prepend_range(rg) (seit C++23) |
void | Container | deque, list, forward_list
|
| Auswirkung | Fügt[6] Kopien von Elementen in rg vor v.begin() ein.
| ||
| Vorbedingung | T ist EmplaceConstructible in C aus *ranges::begin(rg). | ||
| v.push_back(t) | void | Container | basic_string, vector, inplace_vector, deque, list
|
| Auswirkung | Hängt eine Kopie von t an. | ||
| Vorbedingung |
| ||
| v.push_back(rv) (seit C++11) |
void | Container | basic_string, vector, inplace_vector, deque, list
|
| Auswirkung | Hängt eine Kopie von rv an, möglicherweise unter Verwendung von Move-Semantik. | ||
| Vorbedingung | T ist MoveInsertable in C. | ||
| v.append_range(rg) (seit C++23) |
void | Container | vector, inplace_vector, deque, list
|
| Auswirkung | Fügt[6] Kopien von Elementen in rg vor v.end() ein.
| ||
| Vorbedingung | T ist EmplaceConstructible in C aus *ranges::begin(rg). | ||
| v.pop_front() | void | Container | deque, list, forward_list
|
| Auswirkung | Zerstört das erste Element. | ||
| Vorbedingung | a.empty() ist false. | ||
| v.pop_back() | void | Container | basic_string, vector, inplace_vector, deque, list
|
| Auswirkung | Zerstört das letzte Element. | ||
| Vorbedingung | a.empty() ist false. | ||
| v[n] | Ref
|
Container | basic_string, array, vector, inplace_vector, deque
|
| Entspricht return *(v.begin() + n);. | |||
| cv[n] | CRef
|
Container | basic_string, array, vector, inplace_vector, deque
|
| Entspricht return *(cv.begin() + n);. | |||
| v.at(n) | Ref
|
Container | basic_string, array, vector, inplace_vector, deque
|
| Rückgabewert | *(v.begin() + n) | ||
| Ausnahmen | Wirft std::out_of_range, wenn n >= v.size() true ist. | ||
| cv.at(n) | CRef
|
Container | basic_string, array, vector, inplace_vector, deque
|
| Rückgabewert | *(cv.begin() + n) | ||
| Ausnahmen | Wirft std::out_of_range, wenn n >= cv.size() true ist. | ||
| Anmerkungen | |||
| |||
Zusätzlich gilt für jeden Sequenzcontainer
- Ein Konstruktor-Template, das zwei Input-Iteratoren annimmt, und die Member-Funktions-Templates von
insert,append,assign,replace, die zwei Input-Iteratoren annehmen, nehmen nicht an der Überladungsauflösung teil, wenn das entsprechende Template-Argument nicht LegacyInputIterator erfüllt.
|
(seit C++17) |
[bearbeiten] Standardbibliothek
Die folgenden Standardbibliotheks-String-Typen und Container erfüllen die Anforderungen von SequenceContainer
| speichert und manipuliert Zeichenfolgen (Klassenvorlage) | |
| (C++11) |
fest dimensioniertes, inplace, zusammenhängendes Array (Klassenvorlage) |
| reservierbares, zusammenhängendes Array (Klassenvorlage) | |
| (C++26) |
reservierbares, festes Kapazitäts-Array, Inplace, zusammenhängend (Klassenvorlage) |
| Doppelt-endende Warteschlange (Klassenvorlage) | |
| (C++11) |
Einfach verkettete Liste (Klassenvorlage) |
| Doppelt verkettete Liste (Klassenvorlage) |
[bearbeiten] Hinweise zur Verwendung
| Container | Vorteile | Nachteile |
|---|---|---|
| std::vector | Schneller Zugriff, zusammenhängender Speicher | Größtenteils ineffiziente Einfügungen/Löschungen |
| std::inplace_vector | Schneller Zugriff, inplace zusammenhängender Speicher | Feste Kapazität und größtenteils ineffiziente Einfügungen/Löschungen |
| std::array | Schneller Zugriff, inplace zusammenhängender Speicher | Feste Anzahl von Elementen und keine Einfügung/Löschung |
| std::deque | Schneller Zugriff, effiziente Einfügung/Löschung am Anfang/Ende | Ineffiziente Einfügung/Löschung in der Mitte der Sequenz |
| std::list std::forward_list |
Effiziente Einfügung/Löschung in der Mitte der Sequenz | Zugriff ist meistens lineare Zeit |
[bearbeiten] Fehlerberichte
Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | angewendet auf | Verhalten wie veröffentlicht | Korrigiertes Verhalten |
|---|---|---|---|
| LWG 139 | C++98 | die optionalen Operationen sollten nicht für die bezeichneten Container implementiert sein als mit amortisierter Zeit erforderlich |
erforderlich mit amortisierter Zeit |
| LWG 149 | C++98 | v.insert(p, t) gab Iter zurück, währendv.insert(p, n, t) und v.insert(p, n, t) void zurückgaben |
sie alle Iter zurückgeben |
| LWG 151 | C++98 | q1 musste dereferenzierbar sein[1] | er kann nicht dereferenzierbar sein |
| LWG 355 | C++98 | das Aufrufen von v.back() oder v.pop_back() würde--v.end() ausführen, was gefährlich ist[2] |
dekrementiert eine Kopie von v.end() stattdessen |
| LWG 589 | C++98 | die Elemente, auf die i und j verweisenkönnten nicht in C::value_type konvertierbar sein |
sie sind implizit konvertierbar in C::value_type |
| LWG 2194 | C++11 | std::queue, std::priority_queue und std::stack waren auch SequenceContainer[3] |
sie sind keine SequenceContainer |
| LWG 2231 | C++11 | die Anforderung an die Komplexität von v.clear() wurde in C++11 versehentlich weggelassen |
Komplexität als linear bestätigt |
| LWG 3927 | C++98 | operator[] hatte keine implizite Anforderung | die implizite Anforderung hinzugefügt |
- ↑ Es handelt sich um einen Fehler, da er dazu führt, dass das Verhalten von v.erase(v.begin(), v.end()) undefiniert ist, wenn
vein leerer Container ist. - ↑ Wenn der Typ von v.end() ein fundamentaler Typ ist, ist --v.end() ill-formed. Es ist gefährlich, wenn der Typ von v ein Template ist, in diesem Fall kann dieser Fehler schwer zu finden sein.
- ↑ Sie wurden in C++98 nicht als SequenceContainer dokumentiert.