Das übliche Beispiel für C++ 11-bereichsbasierte for () -Schleifen ist immer so einfach:
std::vector<int> numbers = { 1, 2, 3, 4, 5, 6, 7 };
for ( auto xyz : numbers )
{
std::cout << xyz << std::endl;
}
In diesem Fall ist xyz
ein int
. Aber was passiert, wenn wir so etwas wie eine Karte haben? Was ist der Typ der Variablen in diesem Beispiel:
std::map< foo, bar > testing = { /*...blah...*/ };
for ( auto abc : testing )
{
std::cout << abc << std::endl; // ? should this give a foo? a bar?
std::cout << abc->first << std::endl; // ? or is abc an iterator?
}
Wenn es sich bei dem Container, der durchlaufen wird, um etwas Einfaches handelt, sieht es so aus, als ob bereichsbezogene for () -Schleifen uns jedes Element und keinen Iterator geben. Was Nizza ist ... Wenn es ein Iterator wäre, müssten wir es sowieso als erstes dereferenzieren.
Aber ich bin verwirrt, was mich erwartet, wenn es um Dinge wie Karten und Multimaps geht.
(Ich arbeite immer noch mit g ++ 4.4, während bereichsbezogene Loops in g ++ 4.6+ sind. Daher hatte ich noch keine Chance, es zu versuchen.)
Jedes Element des Containers ist ein map<K, V>::value_type
, das ist ein typedef
für std::pair<const K, V>
. Folglich können Sie in C++ 17 oder höher schreiben
for (auto& [key, value]: myMap) {
std::cout << key << " has value " << value << std::endl;
}
oder als
for (const auto& [key, value]: myMap) {
std::cout << key << " has value " << value << std::endl;
}
wenn Sie die Werte nicht ändern möchten.
In C++ 11 und C++ 14 können Sie erweiterte for
- Schleifen verwenden, um jedes Paar für sich zu extrahieren und dann die Schlüssel und Werte manuell zu extrahieren:
for (auto& kv : myMap) {
std::cout << kv.first << " has value " << kv.second << std::endl;
}
Sie können auch die Variable kv
const
markieren, wenn Sie eine schreibgeschützte Ansicht der Werte wünschen.
In C++ 17 heißt dies strukturierte Bindungen , was Folgendes ermöglicht:
std::map< foo, bar > testing = { /*...blah...*/ };
for ( const auto& [ k, v ] : testing )
{
std::cout << k << "=" << v << "\n";
}
Aus diesem Artikel: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2049.pdf
for( type-specifier-seq simple-declarator : expression ) statement
ist syntaktisch äquivalent zu
{
typedef decltype(expression) C;
auto&& rng(expression);
for (auto begin(std::For<C>::begin(rng)), end(std::For<C>::end(rng)); begin != end; ++ begin) {
type-specifier-seq simple-declarator(*begin);
statement
}
}
Sie können also deutlich erkennen, dass abc
in Ihrem Fall std::pair<key_type, value_type >
Ist. Zum Drucken können Sie also auf jedes Element mit abc.first
Und abc.second
Zugreifen.
Wenn Sie nur die Schlüssel/Werte von Ihrer Karte sehen möchten und Boost verwenden möchten, können Sie die Boost-Adapter mit den bereichsbasierten Schleifen verwenden:
for (const auto& value : myMap | boost::adaptors::map_values)
{
std::cout << value << std::endl;
}
es gibt ein äquivalentes boost :: adapters :: key_values
Wenn der Kopierzuweisungsoperator von foo und bar billig ist (z. B. int, char, pointer usw.), können Sie Folgendes tun:
foo f; bar b;
BOOST_FOREACH(boost::tie(f,b),testing)
{
cout << "Foo is " << f << " Bar is " << b;
}