Wie verwende ich eine bereichsbasierte for()-Schleife mit std::map?

Lesezeit: 5 Minuten

Wie verwende ich eine bereichsbasierte for Schleife mit stdmap
Stephan

Das allgemeine Beispiel für bereichsbasierte for()-Schleifen in C++11 ist immer so etwas Einfaches:

std::vector<int> numbers = { 1, 2, 3, 4, 5, 6, 7 };
for ( auto xyz : numbers )
{
     std::cout << xyz << std::endl;
}

In welchem ​​Fall xyz ist ein int. Aber was passiert, wenn wir so etwas wie eine Karte haben? Welchen Typ hat die Variable 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 der Container, der durchlaufen wird, etwas Einfaches ist, sieht es so aus, als würden bereichsbasierte for()-Schleifen uns jedes Element geben, keinen Iterator. Was schön ist … wenn es ein Iterator wäre, müssten wir es sowieso immer zuerst dereferenzieren.

Aber ich bin verwirrt darüber, was mich erwartet, wenn es um Dinge wie Karten und Multimaps geht.

(Ich bin immer noch auf g++ 4.4, während bereichsbasierte Schleifen in g++ 4.6+ sind, also hatte ich noch keine Gelegenheit, es auszuprobieren.)

  • Der Bereich für Anweisungen vollführt einen unheiligen Tanz mit der Standardbibliothek std::begin und std::end Funktionen oder Elementfunktionen unter demselben Namen.

    – Gene Buschujew

    7. August 2011 um 1:55 Uhr

  • @will In einem 3-zeiligen Beispiel verhedderst du dich über den gefälschten Variablennamen?

    – Stefan

    28. Februar 2017 um 21:03 Uhr

Wie verwende ich eine bereichsbasierte for Schleife mit stdmap
Vorlagentypdef

Jedes Element des Containers ist a map<K, V>::value_typedie ein typedef zum 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 nicht vorhaben, die Werte zu ändern.

In C++11 und C++14 können Sie Enhanced verwenden for Schleifen, um jedes Paar einzeln zu extrahieren, und extrahieren Sie dann manuell die Schlüssel und Werte:

for (const auto& kv : myMap) {
    std::cout << kv.first << " has value " << kv.second << std::endl;
}

Sie könnten auch in Betracht ziehen, die zu markieren kv Variable const wenn Sie eine schreibgeschützte Ansicht der Werte wünschen.

In C++17 heißt das strukturierte Bindungenwas Folgendes ermöglicht:

std::map< foo, bar > testing = { /*...blah...*/ };
for ( const auto& [ k, v ] : testing )
{
  std::cout << k << "=" << v << "\n";
}

  • Ist es möglich, a const & auf den Schlüssel, aber ein nicht konstanter Verweis auf den Wert? (denn das macht map::value_type …)

    – Peterchen

    8. November 2017 um 17:03 Uhr

  • @peterchen: k ist const wenn du benutzt for(auto&[k,v]:testing)

    – dalle

    14. November 2017 um 9:18 Uhr

  • cppReferenz zu strukturierten Bindungen en.cppreference.com/w/cpp/language/structured_binding

    – TankorSmash

    14. Dezember 2017 um 3:06 Uhr

  • Wenn Sie mit GCC kompilieren, benötigen Sie Version 7 oder besser für strukturierte Bindungen: gcc.gnu.org/projects/cxx-status.html

    – csknk

    15. Juli 2018 um 12:33 Uhr

1646307611 103 Wie verwende ich eine bereichsbasierte for Schleife mit stdmap
AK

Aus diesem Papier: 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
    }
}

So können Sie deutlich sehen, was ist abc in Ihrem Fall wird std::pair<key_type, value_type >. Zum Drucken können Sie also auf jedes Element zugreifen abc.first und abc.second

Wenn Sie nur die Schlüssel/Werte 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 entsprechendes boost::adaptors::key_values

http://www.boost.org/doc/libs/1_51_0/libs/range/doc/html/range/reference/adaptors/reference/map_values.html

1646307612 286 Wie verwende ich eine bereichsbasierte for Schleife mit stdmap
Balki

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;
}

  • Das erste Code-Snippet verwendet kein „C++11 Range-based for()“. Es ist keine Antwort auf “C++11: Wie verwende ich eine bereichsbasierte for()-Schleife mit std::map?”

    – Isoiphon

    1. Februar 2014 um 4:54 Uhr

  • @ytj Es wird bereits in der Antwort erwähnt, dass es nicht funktioniert. Ich möchte das nicht entfernen, damit neue Benutzer es nicht versuchen müssen, um die Tatsache erneut herauszufinden.

    – Balki

    3. Juli 2014 um 15:11 Uhr

  • Das erste Code-Snippet verwendet kein „C++11 Range-based for()“. Es ist keine Antwort auf “C++11: Wie verwende ich eine bereichsbasierte for()-Schleife mit std::map?”

    – Isoiphon

    1. Februar 2014 um 4:54 Uhr

  • @ytj Es wird bereits in der Antwort erwähnt, dass es nicht funktioniert. Ich möchte das nicht entfernen, damit neue Benutzer es nicht versuchen müssen, um die Tatsache erneut herauszufinden.

    – Balki

    3. Juli 2014 um 15:11 Uhr

923000cookie-checkWie verwende ich eine bereichsbasierte for()-Schleife mit std::map?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy