Zakresowa pętla for.

Poprzednio rozmawialiśmy o znaczeniu słowa kluczowego auto w C++11. Zakresowa pętla for jest często używana w parze ze słowem auto. Sam pomysł jest rozwinięciem koncepcji zwykłej pętli for o funkcjonalności, które w innych językach programowania są realizowane np. poprzez pętlę foreach.

O co chodzi i jak to działa ?

W C++11 zakresowa pętla for pozwala iterować przez kolekcje elementów, a dokładniej przez zakres, który jest definiowany iteratorami begin oraz end. Oznacza to, że kolekcja, którą chcemy przejść, musi mieć zdefiniowane takie iteratory. Takie wymogi spełniają z automatu niemal wszystkie standardowe kontenery, zdefiniowane w STL-u, ale też np. std::string.

Dobry przykład wygląda następująco:

#include <iostream> 
#include <string>  

int main(int argc, char* argv[]) 
{     
    std::string text = "sample text";      

    for(const char& c : text)     
    {         
        std::cout << c << std::endl;     
    }      

    return 0; 
}

Ten prosty kod wyświetla każdy znak tekstu w osobnej linii. Na przykładzie widać, jak wygląda składnia wyrażenia: słowo kluczowe for się nie zmienia, ale w nawiasie deklarujemy zmienną określonego typu (która będzie przechowywać każdy kolejny element). Następnie mamy dwukropek, a po nim nazwa zmiennej, która oznacza interesującą nas kolekcję. W efekcie podczas każdej iteracji zmienna c odzwierciedla każdy kolejny element kolekcji text.

Kolejny przykład:

#include <iostream> 
#include <vector>  

int main(int argc, char* argv[]) 
{     
    std::vector<int> values = {1, 3, 5, 7};      

    for(auto& v : values)     
    {         
        v *= 2;     
    }      

    for(int v : values)     
    {         
        std::cout << v << " ";     
    }      

    std::cout << std::endl;      

    return 0; 
}

Jak widać, możemy wygodnie łączyć słowo kluczowe auto z zakresową pętlą for. Panują tutaj ogólne zasady, które definiuje język C++. Jeśli chcemy zmieniać wartość elementów w kolekcji, możemy w pętli zadeklarować zmienną tymczasową jako referencję – i już. Jeśli nie chcemy, aby zachodziło kopiowanie elementu (bo to może być np. czasochłonne), ale jednocześnie nie chcemy umożliwiać modyfikacji elementu, rozwiązanie przychodzi samo: stała referencja.

Intuicyjnie widać już, w jakich sytuacjach przydaje się nam zakresowa pętla for. Są to sytuacje, w których nie interesuje nas liczba elementów w kolekcji oraz ich indeksy, ale chcemy wykonać jakąś akcję na każdym kolejnym elemencie. Finalnie kod jest zrozumiały i dużo krótszy, a więc czytelniejszy.