HOWTO · C++
Der value_type in STL-Containern in C++
Die STL ist eine Abkürzung für die Standard Template Library. Es handelt sich um eine Reihe von Datenstrukturen und Algorithmen, die zur Implementierung generischer Container und Funktionen für die Programmiersprache C++ verwendet werden.
Auf dieser Seite
value_type eines STL-Containers ist ein Typalias für den Typ der darin gespeicherten Elemente. Bei std::vector<int> ist dieser Typ int; bei einem assoziativen Container wie std::map<std::string, int> ist es ein Schlüssel-Wert-Paar. Sie können den Alias über den Containertyp angeben und in generischem Code verwenden, wenn der Containertyp ein Template-Parameter ist.
Was value_type bedeutet
Container definieren value_type, um den Typ jedes Elements ihrer Sequenz oder Sammlung anzugeben. Zum Beispiel ist std::vector<int>::value_type gleich int, während der Elementtyp einer Map ein Paar aus Schlüssel und zugeordnetem Wert ist. Bei std::map<std::string, int> ist dieses Element ein std::pair: Das erste Mitglied ist der Schlüssel, das zweite der zugehörige Wert. Der Schlüssel ist im gespeicherten Paar konstant, damit die Sortierung gültig bleibt. Der Alias ermöglicht es Code, der mit einem Container arbeitet, auf dessen Elementtyp zu verweisen, ohne den Typ separat ausschreiben zu müssen. Er beschreibt ein einzelnes gespeichertes Element, nicht das Containerobjekt selbst: Die Elemente eines Vektors mit Ganzzahlen haben den Typ int, während der Vektor einen eigenen Containertyp hat.
Auf den value_type eines Containers zugreifen
Verwenden Sie vor dem Scope-Operator den Typ des Containers: std::vector<int>::value_type. Das ist ein Typname. Daher ist myVector::value_type ungültig, wenn myVector ein Objekt ist. Wenn Sie einen lokalen Namen für den Elementtyp möchten, schreiben Sie using Element = std::vector<int>::value_type;. Die Schreibweise Container::value_type wird auch verwendet, wenn Container ein Template-Parameter ist. Da es sich um einen abhängigen Typnamen handelt, verlangt C++ davor das Schlüsselwort typename. Anhand der Template-Deklaration allein kann der Compiler nicht erkennen, ob ein abhängiger Name einen Typ oder einen Wert bezeichnet; typename macht diese Interpretation ausdrücklich. Im gewöhnlichen Code, in dem der Containertyp bereits feststeht, wie bei std::vector<int>::value_type, erkennt der Compiler den verschachtelten Typ direkt. Eine solche Unterscheidung ist dann nicht nötig.
value_type in generischem Code verwenden
Eine generische Funktion kann typename Container::value_type verwenden, um den Elementtyp zu benennen und dabei verschiedene Container zu akzeptieren. Dieses Beispiel gibt jedes Element eines Vektors und einer Liste aus:
Führen Sie dieses Beispiel aus:
#include <iostream>
#include <list>
#include <string>
#include <vector>
template <typename Container>
void printElements(const Container& container) {
for (const typename Container::value_type& element : container) {
std::cout << element << '\n';
}
}
int main() {
const std::vector<int> numbers{1, 2, 3};
const std::list<std::string> colors{"red", "blue"};
printElements(numbers);
printElements(colors);
}
Die beobachtete Ausgabe lautet:
1
2
3
red
blue
In der Funktion wird Container aus dem Argument abgeleitet. Deshalb funktioniert derselbe Funktionskörper sowohl mit std::vector<int> als auch mit std::list<std::string>. Container::value_type hängt von diesem Template-Parameter ab; deshalb steht in der Deklaration typename. Die Schleife bindet jedes Element über eine konstante Referenz: Sie kann das Element lesen, ohne es zu kopieren, und über diese Referenz das Containerelement nicht ändern. Dieses Muster ist nützlich, wenn eine Funktion den Elementtyp für eine lokale Variable, einen Parameter oder einen Rückgabetyp benennen muss, aber nicht von einem bestimmten Container abhängen soll. Der Container muss weiterhin die verwendeten Operationen unterstützen; hier ist die gemeinsame Voraussetzung die bereichsbasierte Iteration. Die unveränderte Beispielausgabe enthält die englischen Farbnamen red und blue.
Was value_type nicht leistet
value_type benennt einen Elementtyp; der Alias reserviert oder gibt keinen Speicher frei. Container und ihre Allokatoren verwalten den Speicher nach ihren jeweiligen Regeln. Der Alias macht einen Container auch nicht grundsätzlich schneller oder sicherer als einen anderen. Sein praktischer Vorteil besteht hier darin, dass generischer Code den vom jeweiligen Container bereitgestellten Elementtyp benennen kann, auch bei benutzerdefinierten Elementtypen. value_type verspricht nicht, dass alle Container mit diesem Alias dieselbe Schnittstelle haben: Der Code darf sich nur auf Operationen stützen, die von den verwendeten Containern unterstützt werden. Wählen Sie einen Container anhand der benötigten Operationen und Leistungseigenschaften aus und verwenden Sie seinen Alias, wenn sich der Elementtyp nach dieser Wahl richten soll. Kurz gesagt: value_type teilt generischem Code mit, was ein Element ist; der Alias bestimmt nicht, wie der Container diese Elemente speichert oder verwaltet.