Co nowego w C++11? Część 1

Nie tak dawno we wrześniu został oficjalnie wydany nowy standard języka C++: C++11. Po 8 latach od poprzedniej edycji tego języka wprowadzono dosyć dużo nowinek zarówno w standardowej bibliotece STL jak i w samej składni języka. Postaram się pokrótce przedstawić (mam nadzieje, iż w kilku częściach) nowinki, które najbardziej mnie przypadły do gustu i które są wspierane przez co najmniej jeden z dwóch kompilatorów: GCC i/lub MS VC++. Napisałem “co najmniej”, gdyż na chwilę obecna niestety nie wszystkie kompilatory wspierają bądź co bądź jeszcze świeży standard. Aczkolwiek wiele rzeczy już jest zaimplementowane.

Przechodząc już do konkretów.. Pierwszym elementem, który chciałbym opisać jest nowe słowo kluczowe auto. Może nie jest ono do końca nowe, gdyż istniało już w poprzednich wersjach standardu, jednakże kompletnie zmieniło ono znaczenie. Zadaniem słowa kluczowego auto jest ułatwienie i skrócenie czasu pisania programów. Chodzi tutaj o automatyczne (ale co najważniejsze statyczne) wnioskowanie typu zmiennej na podstawie wyrażenia r-value na etapie kompilacji kodu.

Na przykład:

    auto i = 5;  		// zmienna typu int
    auto j = 2.5;		// zmienna typu float
    std::vector<double> v;
    auto it = v.begin(); 	// zmienna typu std::vector<double>::iterator

Jak widać w pierwszym i drugim przykładzie kodu co prawda niewiele zostało zaoszczędzone. Ale załóżmy, że w naszym projekcie powszechnie stosujemy iteratorów oraz za każdym razem chcemy deklarować nowe zmienne przechowujące odpowiedni iterator. W takim przypadku należy zazwyczaj podać pełna nazwę typu, np.: std::vector<double>::iterator. Pól biedy gdy mamy do czynienia z szablonami o jednym argumencie, gorzej natomiast, gdy chcemy iterować po nieuporządkowanej mapie której kluczem jest para dwóch liczb całkowitych a wartościami tablice liczb zmiennoprzecinkowych. No ok, może przypadek trochę wyolbrzymiony, ale porównajmy zapisy:

    std::unordered_map<std::pair<int, int>, std::vector<double> > collection;
    std::unordered_map<std::pair<int, int>, std::vector<double> >::iterator it_manual = collection.begin();
    auto it_auto = collection.begin();

oraz pętle:

    for (std::unordered_map<std::pair<int, int>, std::vector<double> >::iterator it_manual = collection.begin(); it != collection.end; ++it) {
        ....
    }
    for (auto it_auto = collection.begin(); it != collection.end; ++it) {
        ....
    }

Jak można łatwo zauważyć otrzymujemy zarówno duży zysk płynący zarówno z oszczędności pisania kodu jak i jego czytelności, no i najważniejsze, że nie potrzeba już pamiętać jakiego dokładnie typu była nasza kolekcja.