C++ benannte Anforderungen: AllocatorAwareContainer (seit C++11)
Ein AllocatorAwareContainer ist ein Container, der eine Instanz eines Allocators hält und diese Instanz in all seinen Memberfunktionen verwendet, um Speicher zuzuweisen und freizugeben und um Objekte in diesem Speicher zu konstruieren und zu zerstören (solche Objekte können Container-Elemente, Knoten oder bei Unordered-Containern Bucket-Arrays sein), mit der Ausnahme, dass std::basic_string-Spezialisierungen die Allocatoren nicht für die Konstruktion/Zerstörung ihrer Elemente verwenden(seit C++23).
Die folgenden Regeln gelten für Container-Konstruktion
- Kopierkonstruktoren von AllocatorAwareContainer erhalten ihre Instanzen des Allocators durch Aufruf von std::allocator_traits<allocator_type>::select_on_container_copy_construction auf dem Allocator des zu kopierenden Containers.
- Move-Konstruktoren erhalten ihre Instanzen von Allocators durch Move-Konstruktion aus dem Allocator des alten Containers.
- Alle anderen Konstruktoren nehmen einen const allocator_type&-Parameter entgegen.
Die einzige Möglichkeit, einen Allocator zu ersetzen, ist die Kopierzuweisung, die Move-Zuweisung und der Swap
- Die Kopierzuweisung ersetzt den Allocator nur, wenn std::allocator_traits<allocator_type>::propagate_on_container_copy_assignment::value true ist.
- Die Move-Zuweisung ersetzt den Allocator nur, wenn std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value true ist.
- Swap ersetzt den Allocator nur, wenn std::allocator_traits<allocator_type>::propagate_on_container_swap::value true ist. Insbesondere werden die Allocator-Instanzen durch einen unqualifizierten Aufruf der nicht-Member-Funktion swap ausgetauscht, siehe Swappable.
Hinweis: Das Verhalten beim Vertauschen zweier Container mit ungleichen Allocators, wenn propagate_on_container_swap false ist, ist undefiniert.
- Der Zugriffsor
get_allocator()ruft eine Kopie des Allocators ab, der zum Konstruieren des Containers verwendet wurde oder durch den letzten Allocator-Ersetzungsoperation installiert wurde.
Inhalt |
[edit] Anforderungen
Ein Typ erfüllt AllocatorAwareContainer, wenn er Container erfüllt und, gegeben die folgenden Typen und Werte, die semantischen und Komplexitätsanforderungen in den folgenden Tabellen erfüllt sind
| Typ | Definition |
X
|
ein AllocatorAwareContainer-Typ |
T
|
der value_type von X |
A
|
der von X verwendete Allocator-Typ |
| Wert | Definition |
| a, b | nicht-const lvalues vom Typ X |
| c | ein lvalue vom Typ const X |
| t | ein lvalue oder ein const rvalue vom Typ X |
| rv | ein non-const rvalue vom Typ X |
| m | ein Wert vom Typ A |
[edit] Typen
| Name | Typ | Anforderung |
|---|---|---|
| typename X::allocator_type | A
|
X::allocator_type::value_type und X::value_type sind identisch. |
[edit] Anweisungen
| Anweisung | Semantik | Komplexität | |
|---|---|---|---|
| X u; X u = X(); |
Vorbedingung | A ist DefaultConstructible. |
Konstante |
| Nachbedingung | u.empty() und u.get_allocator() == A() sind beide true. | ||
| X u(m); | Nachbedingung | u.empty() und u.get_allocator() == m sind beide true. | Konstante |
| X u(t, m); | Vorbedingung | T ist CopyInsertable in X. |
Linear |
| Nachbedingung | u == t und u.get_allocator() == m sind beide true. | ||
| X u(rv); | Nachbedingung |
|
Konstante |
| X u(rv, m); | Vorbedingung | T ist MoveInsertable in X. |
|
| Nachbedingung |
| ||
[edit] Ausdrücke
| Ausdruck | Typ | Semantik | Komplexität | |
|---|---|---|---|---|
| c.get_allocator() | A
|
Keine direkte semantische Anforderung. | Konstante | |
| a = t | X&
|
Vorbedingung | T ist CopyInsertable in X und CopyAssignable. |
Linear |
| Nachbedingung | a == t ist true. | |||
| a = rv | X&
|
Vorbedingung | Wenn der Allocator durch Move-Zuweisung **nicht** ersetzt wird (siehe oben), dann ist T MoveInsertable in X und MoveAssignable. |
Linear |
| Auswirkung | Alle vorhandenen Elemente von a werden entweder move-assigned oder zerstört. | |||
| Nachbedingung | Wenn a und rv nicht auf dasselbe Objekt verweisen, ist a gleich dem Wert, den rv vor der Zuweisung hatte. | |||
| a.swap(b) | void | Auswirkung | Tauscht den Inhalt von a und b. | Konstante |
[edit] Hinweise
AllocatorAwareContainers rufen immer std::allocator_traits<A>::construct(m, p, args) auf, um ein Objekt vom Typ T an p unter Verwendung von args zu konstruieren, wobei m == get_allocator() ist. Der Standard-construct in std::allocator ruft ::new((void*)p) T(args) auf(bis C++20)std::allocator hat kein construct-Mitglied und std::construct_at(p, args) wird beim Konstruieren von Elementen aufgerufen(seit C++20), aber spezialisierte Allocators können eine andere Definition wählen.
[edit] Standardbibliothek
Alle Standardbibliotheks-Zeichenfolgentypen und Container (außer std::array und std::inplace_vector) sind AllocatorAwareContainers.
| speichert und manipuliert Zeichenfolgen (Klassenvorlage) | |
| Doppelt-endende Warteschlange (Klassenvorlage) | |
| (C++11) |
Einfach verkettete Liste (Klassenvorlage) |
| Doppelt verkettete Liste (Klassenvorlage) | |
| reservierbares, zusammenhängendes Array (Klassenvorlage) | |
| Sammlung von Schlüssel-Wert-Paaren, sortiert nach Schlüsseln, Schlüssel sind eindeutig (Klassenvorlage) | |
| Sammlung von Schlüssel-Wert-Paaren, sortiert nach Schlüsseln (Klassenvorlage) | |
| Sammlung eindeutiger Schlüssel, sortiert nach Schlüsseln (Klassenvorlage) | |
| Sammlung von Schlüsseln, sortiert nach Schlüsseln (Klassenvorlage) | |
| (C++11) |
Sammlung von Schlüssel-Wert-Paaren, gehasht nach Schlüsseln, Schlüssel sind eindeutig (Klassenvorlage) |
| (C++11) |
Sammlung von Schlüssel-Wert-Paaren, gehasht nach Schlüsseln (Klassenvorlage) |
| (C++11) |
Sammlung eindeutiger Schlüssel, gehasht nach Schlüsseln (Klassenvorlage) |
| (C++11) |
Sammlung von Schlüsseln, gehasht nach Schlüsseln (Klassenvorlage) |
[edit] 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 2839 | C++11 | Selbst-Move-Zuweisung von Standardcontainern war nicht erlaubt | erlaubt, aber das Ergebnis ist undefiniert |