poniedziałek, 5 maja 2014

C++11

W stosunku do poprzedniej wersji języka C++ wprowadzono m.in. następujące nowości:
  • typ long long,
  • typy char16_t i char32_t dla zmiennych bez znaku odpowiednio o szerokości 16 i 32 bitów (literały znakowe i napisowe dla typu char16_t są poprzedzone literą u natomiast dla char32_t są poprzedzone literą U),
  • obsługa dla wariantu kodowania znaków UTF-8 (literał poprzedzamy przedrostkiem "u8"),
  • łańcuch literalny, który sprawia, że znaki nie są interpretowane przez kompilator czyli można je wpisywać wprost w łańcuchu jak np. znaki specjalne łącznie ze znakami cudzysłowu (przed literałem dodajemy tutaj "R"),
  • inicjalizacja zmiennych: "int zmienna{1};" oraz instrukcja "int zmienna{}", która wstawia do zmiennej wartość 0, 
  • podobnie inicjalizacja tablic: "double tablica[2] {1.26e4, 1.11e-8};"  i wypełnianie wartościami zerowymi w postaci "double tablica[10] {};",
  • nadawanie wartości początkowych łańcuchom znaków: "char znaki[] = {"Znaki"};" lub "char znaki[] {"Znaki"};", a także "string signs = {"Znaki"};" lub "string signs {"Znaki"};",
  • podobnie sytuacja ma miejsce w przypadku struktur: "struct struktura {"Pole 1", 2, 3.0}" i dla inicjalizacji wartościami zerowymi "struct struktura {}",
  • przyrostki "LL" i "ULL" dla literałów odpowiednio typu long long i unsigned long,
  • dedukowanie typu zmiennej na podstawie typu wartości inicjalizującej gdzie np. instrukcja "auto zmienna = 0.0" określa zmienną jako double, a instrukcja "auto zmienna = 0" jako int,
  • klasa szablonowa array będąca skuteczną i bezpieczną alternatywą dla tablic wbudowanych o stałym rozmiarze,
  • pętla zakresowa for postaci "for (typ zmienna : tablica)" gdzie "typ" jest typem danych przechowywanych w "tablica", a "zmienna" przyjmuje wartość pierwszego elementu z danego zestawu danych (pętla przechodzi po wszystkich elementach tablicy),
  • referencja do r-wartości deklarowana jest np. jako "int && r_value = (2 * zmienna  + 20);" co niedozwolone jest dla zwykłej referencji,
  • wyrażenie "decltype" umożliwia określenie tego samego typu zmiennej, np. wyrażenie "decltype(zmienna_1) zmienna_2;" przypisuje "zmienna_2" typ "zmienna_1", a z kolei wyrażenie "decltype(zmienna_1 + zmienna_2) zmienna_3;" przypisuje "zmienna_3" typ wyrażenia ujętego w nawiasy,
  • opóźniona deklaracja typu zwracanego: "auto funkcja(typ zmienna_1, typ zmienna_2) -> double;" czy też "auto funkcja(typ zmienna_1, typ zmienna_2) -> decltype(zmienna_1 + zmienna_2);",
  • specyfikator thread_local wskazujący, że czas życia zmiennej jest równy czasowi życia wątku zawierającego zmienną (zmienna z tym przydomkiem jest dla wątku tym samym co zmienna statyczna dla całego programu),
  • inicjalizacja operatorem new: możliwe są np. takie instrukcje jak "int * tablica = new int[2] {1, 2};" czy też "double * wskaznik = new int {1};",
  • inicjalizacja obiektu klasy za pomocą listy: "klasa obiekt = {"Argument", 1, 2.0};",
  • wyliczenia z własnym zasięgiem: deklarując typ wyliczeniowy jako "enum nazwa_klasy nazwa_typu_wyliczeniowego {Element_1, Element_2}" możemy odwoływać się do elementów wyliczenia np. jako "nazwa_typu_wyliczeniowego nazwa_odniesienia = nazwa_typu_wyliczeniowego::Element_1" co pozwala na eliminację problemu kolizji nazw elementów wyliczeń poprzez nadanie im zasięgu klasy,
  • w C++11 domyślnym typem wewnętrznym wyliczenia jest int jednak można ręcznie określić pożądanym typ wewnętrzny za pomocą wyrażenia o postaci np. "enum nazwa_klasy : short nazwa_typu_wyliczeniowego {Element1, Element2}" (typ wewnętrzny musi być typem całkowitoliczbowym,
  • w C++98 słowo "explicit" nie działa z funkcjami konwersji w przeciwieństwie do C++11,
  • notacja "nullptr" określająca wskaźnik pusty,
  • inicjalizacja składowych klas: zapis "class klasa { int zmienna = 1; };" równoważny jest zapisowi "klasa::klasa() : zmienna(1) { }" jako liście inicjalizacyjnej,
  • szablon będący argumentem typu dla innego szablonu: w poprzedniej wersji C++ w obawie przed mylną interpretacją operatora przesunięcia bitowego należało pisać deklarację w postaci np. "szablon < klasa<int> > obiekt;" natomiast w C++ ten problem został już zażegnany,
  • szablonowe aliasy typów: zamiast stosowania deklaracji np. "typedef std::klasa<int, 1> aliast" możemy wykorzystać instrukcję "template<typename type> using alias = std::klasa<type, 1>" co sprawia, że pisząc np. "alias<double> obiekt" określamy, iż "obiekt" jest typu "std::klasa<double, 1>",
  • klasa kontenerowa forward_list, która implementuje zwyczajną listę jednokierunkową,
  • szablon klasy array,
  • nieuporządkowane kontenery asocjacyjne typu unordered_set, unordered_multiset, unordered_map i unordered_multimap,
  • szablon initializer_list, który pozwala na stosowanie składni listy inicjalizującej do inicjalizowania kontenerów STL listami wartości,
Źródło: Prata S., Język C++. Szkoła programowania, Wydanie VI, Helion SA, 2012