Itereer door een C++ Vector met behulp van een ‘for’-lus

Ik ben nieuw in de C++-taal. Ik ben vectoren gaan gebruiken en heb gemerkt dat in alle code die ik zie itereren door een vector via indices, de eerste parameter van de for-lus altijd iets is dat op de vector is gebaseerd. In Java zou ik zoiets als dit kunnen doen met een ArrayList:

for(int i=0; i < vector.size(); i++){
   vector[i].doSomething();
}

Is er een reden waarom ik dit niet zie in C++? Is het een slechte gewoonte?


Antwoord 1, autoriteit 100%

Is er een reden waarom ik dit niet zie in C++? Is het een slechte gewoonte?

Nee. Het is geen slechte gewoonte, maar de volgende benadering maakt uw code een zekere flexibiliteit.

Gewoonlijk gebruikt pre-C++11 de code voor het herhalen van containerelementen iterators, zoiets als:

std::vector<int>::iterator it = vector.begin();

Dit komt omdat het de code flexibeler maakt.

Alle standaard bibliotheekcontainers ondersteunen en bieden iterators. Mocht u op een later moment van ontwikkeling naar een andere container moeten overstappen, dan hoeft deze code niet te worden gewijzigd.

Opmerking: Het schrijven van code die werkt met elke mogelijke standaard bibliotheekcontainer is niet zo eenvoudig als het lijkt.


Antwoord 2, autoriteit 123%

De reden waarom je een dergelijke praktijk niet ziet, is nogal subjectief en kan geen definitief antwoord hebben, omdat ik veel van de code heb gezien die jouw genoemde manier gebruikt in plaats van iterator-achtige code.

Het volgende kan redenen zijn waarom mensen de vector.size() manier van lussen niet overwegen:

  1. Paranoïde zijn over het aanroepen van size() elke keer in de loop
    voorwaarde. Maar of het is een non-issue of het kan triviaal zijn
    vast
  2. Voorkeur voor std::for_each() boven de for-lus zelf
  3. Later de container wijzigen van std::vector naar een andere (bijv.
    map, list) zullen ook de verandering van het looping-mechanisme vereisen,
    omdat niet elke container size()-loopstijl ondersteunt

C++11 biedt een goede mogelijkheid om door de containers te bewegen. Dat heet “range based for loop” (of “enhanced for loop” in Java).

Met weinig code kun je door de volledige (verplichte!) std::vector:

vector<int> vi;
...
for(int i : vi) 
  cout << "i = " << i << endl;

Antwoord 3, autoriteit 98%

De schoonste manier om door een vector te itereren is via iterators:

for (auto it = begin (vector); it != end (vector); ++it) {
    it->doSomething ();
}

of (gelijk aan het bovenstaande)

for (auto & element : vector) {
    element.doSomething ();
}

Voorafgaand aan C++0x moet je auto vervangen door het iteratortype en lidfuncties gebruiken in plaats van globale functies begin en einde.

Dit is waarschijnlijk wat je hebt gezien. Ten opzichte van de aanpak die je noemt, is het voordeel dat je niet sterk afhankelijk bent van het type vector. Als u vector wijzigt in een andere klasse “collection-type”, zal uw code waarschijnlijk nog steeds werken. U kunt echter ook iets soortgelijks in Java doen. Conceptueel is er niet veel verschil; C++ gebruikt echter sjablonen om dit te implementeren (in vergelijking met generieken in Java); daarom werkt de aanpak voor alle typen waarvoor de functies begin en end zijn gedefinieerd, zelfs voor niet-klassetypen zoals statische arrays. Zie hier: Hoe werkt de range-based for voor gewone arrays?


Antwoord 4, autoriteit 32%

De juiste manier om dat te doen is:

for(std::vector<T>::iterator it = v.begin(); it != v.end(); ++it) {
    it->doSomething();
 }

Waarbij T het type is van de klasse binnen de vector. Als de klas bijvoorbeeld CActivity was, schrijf dan gewoon CActivity in plaats van T.

Dit type methode werkt op elke STL (niet alleen vectoren, wat een beetje beter is).

Als je nog steeds indexen wilt gebruiken, is de volgende manier:

for(std::vector<T>::size_type i = 0; i != v.size(); i++) {
    v[i].doSomething();
}

Antwoord 5, autoriteit 8%

Het gebruik van de auto-operator maakt het echt gemakkelijk te gebruiken omdat men zich geen zorgen hoeft te maken over het gegevenstype en de grootte van de vector of een andere gegevensstructuur

Vector herhalen met auto en for-lus

vector<int> vec = {1,2,3,4,5}
for(auto itr : vec)
    cout << itr << " ";

Uitvoer:

1 2 3 4 5

Je kunt deze methode ook gebruiken om sets en lijsten te herhalen. Door auto te gebruiken, wordt automatisch het gegevenstype gedetecteerd dat in de sjabloon wordt gebruikt en kunt u deze gebruiken.
Dus zelfs als we een vector van string of char hadden, werkt dezelfde syntaxis prima


Antwoord 6, autoriteit 7%

Er zijn een aantal sterke redenen om iterators te gebruiken, waarvan sommige hier worden genoemd:

Als u later van container wisselt, wordt uw code niet ongeldig.

d.w.z. als u van een std::vector naar een std::list of std::set gaat, kunt u geen numerieke indices gebruiken om uw ingesloten waarde te krijgen. Het gebruik van een iterator is nog steeds geldig.

Runtime-vangst van ongeldige iteratie

Als je je container in het midden van je lus aanpast, zal de volgende keer dat je je iterator gebruikt een ongeldige iterator-uitzondering genereren.


Antwoord 7, autoriteit 6%

Een correcte manier om de vector te herhalen en de waarden ervan af te drukken is als volgt:

#include<vector>
// declare the vector of type int
vector<int> v;
// insert elements in the vector
for (unsigned int i = 0; i < 5; ++i){
    v.push_back(i);
}
// print those elements
for (auto it = v.begin(); it != v.end(); ++it){
    std::cout << *it << std::endl;
}

Maar in dit geval is het in ieder geval prettiger om een ​​op een bereik gebaseerde for-lus te gebruiken:
for (auto x: v) std::cout << x << "\n";
(Je kunt ook & toevoegen na auto om van x een verwijzing naar de elementen te maken in plaats van een kopie ervan. Het lijkt dan erg op elkaar naar de bovenstaande iteratorgebaseerde benadering, maar gemakkelijker te lezen en te schrijven.)


Antwoord 8, autoriteit 4%

Het verbaasde me dat niemand zei dat het herhalen van een array met een integer-index het voor jou gemakkelijk maakt om foutieve code te schrijven door een array met de verkeerde index te subscripten. Als u bijvoorbeeld geneste lussen heeft met i en j als indices, kunt u een array onjuist subscripten met j in plaats van i en zo een fout in het programma introduceren.

Daarentegen zijn de andere vormen die hier worden vermeld, namelijk de op bereik gebaseerde for-lus en iterators, een stuk minder foutgevoelig. De semantiek van de taal en het typecontrolemechanisme van de compiler voorkomen dat je per ongeluk een array opent met de verkeerde index.


Antwoord 9, autoriteit 3%

Met STL gebruiken programmeurs iterators voor het doorlopen van containers, aangezien iterator een abstract concept is, geïmplementeerd in alle standaard containers. std::list heeft bijvoorbeeld helemaal geen operator [].


Antwoord 10, autoriteit 2%

Hier is een eenvoudigere manier om waarden in vectoren te herhalen en af ​​te drukken.

for(int x: A) // for integer x in vector A
    cout<< x <<" "; 

Antwoord 11, autoriteit 2%

 //different declaration type
    vector<int>v;  
    vector<int>v2(5,30); //size is 5 and fill up with 30
    vector<int>v3={10,20,30};
    //From C++11 and onwards
    for(auto itr:v2)
        cout<<"\n"<<itr;
     //(pre c++11)   
    for(auto itr=v3.begin(); itr !=v3.end(); itr++)
        cout<<"\n"<<*itr;

Antwoord 12

Als u

. gebruikt

std::vector<std::reference_wrapper<std::string>> names{ };

Vergeet niet, als je auto in de for-lus gebruikt, om ook get te gebruiken, zoals dit:

for (auto element in : names)
{
    element.get()//do something
}

LEAVE A REPLY

Please enter your comment!
Please enter your name here

16 − seven =

Other episodes