Nowoczesny C++ Rafał Wasilewski 1

Podobne dokumenty
Programowanie obiektowe w C++ Wykład 12

IMIĘ i NAZWISKO: Pytania i (przykładowe) Odpowiedzi

Programowanie obiektowe Wykład 3. Dariusz Wardowski. dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/21

PARADYGMATY PROGRAMOWANIA Wykład 4

Szablony klas, zastosowanie szablonów w programach

Programowanie i struktury danych. Wykład 4 Dr Piotr Cybula

Lab 9 Podstawy Programowania

C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

Programowanie współbieżne Wykład 8 Podstawy programowania obiektowego. Iwona Kochaoska

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 3. Karol Tarnowski A-1 p.

Wykład 8: klasy cz. 4

Informacje ogólne. Karol Trybulec p-programowanie.pl 1. 2 // cialo klasy. class osoba { string imie; string nazwisko; int wiek; int wzrost;

Wykład 4: Klasy i Metody

TEMAT : KLASY DZIEDZICZENIE

C++11. C++ 11 wybrane elementy. C++11: referencje do rvalue C++ 11: C++11: referencje do rvalue. C++11: referencje do rvalue. Referencje do rvalue

Podstawy programowania skrót z wykładów:

PROE wykład 3 klasa string, przeciążanie funkcji, operatory. dr inż. Jacek Naruniec

Programowanie w języku C++

public: // interfejs private: // implementacja // składowe klasy protected: // póki nie będziemy dziedziczyć, // to pole nas nie interesuje

Obszar statyczny dane dostępne w dowolnym momencie podczas pracy programu (wprowadzone słowem kluczowym static),

Wskaźniki. Informatyka

Programowanie, część I

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

Wykład 1: Wskaźniki i zmienne dynamiczne

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy INNE SPOSOBY INICJALIZACJI SKŁADOWYCH OBIEKTU

PROE wykład 2 operacje na wskaźnikach. dr inż. Jacek Naruniec

Instytut Mechaniki i Inżynierii Obliczeniowej Wydział Mechaniczny Technologiczny Politechnika Śląska

Programowanie obiektowe w języku C++ dr inż. Jarosław Forenc

W2 Wprowadzenie do klas C++ Klasa najważniejsze pojęcie C++. To jest mechanizm do tworzenia obiektów. Deklaracje klasy :

Podstawy programowania w języku C++

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu.

ZASADY PROGRAMOWANIA KOMPUTERÓW

Zaawansowane programowanie w języku C++ Funkcje uogólnione - wzorce

Konstruktor kopiujacy

Zaawansowane programowanie w języku C++ Klasy w C++

STL: Lekcja 1&2. Filozofia STL

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy KONSTRUKTORY

Strona główna. Strona tytułowa. Programowanie. Spis treści. Sobera Jolanta Strona 1 z 26. Powrót. Full Screen. Zamknij.

Wskaźnik może wskazywać na jakąś zmienną, strukturę, tablicę a nawet funkcję. Oto podstawowe operatory niezbędne do operowania wskaźnikami:

Podstawy programowania w języku C++

Konstruktory. Streszczenie Celem wykładu jest zaprezentowanie konstruktorów w Javie, syntaktyki oraz zalet ich stosowania. Czas wykładu 45 minut.

Klasy Obiekty Dziedziczenie i zaawansowane cechy Objective-C

Programowanie obiektowe. Materiały przygotował: mgr inż. Wojciech Frohmberg

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy INNE SPOSOBY INICJALIZACJI SKŁADOWYCH OBIEKTU

Automatyczne tworzenie operatora = Integer2& operator=(const Integer& prawy) { zdefiniuje. Integer::operator=(ri);

Java: kilka brakujących szczegółów i uniwersalna nadklasa Object

Podczas dziedziczenia obiekt klasy pochodnej może być wskazywany przez wskaźnik typu klasy bazowej.

Automatyczne tworzenie operatora = Integer2& operator=(const Integer& prawy) {

Jeśli chcesz łatwo i szybko opanować podstawy C++, sięgnij po tę książkę.

6 Niektóre nowe cechy standardu C++11

Java - tablice, konstruktory, dziedziczenie i hermetyzacja

Automatyczne tworzenie operatora = Integer2& operator=(const Integer& prawy) {

Języki programowania obiektowego Nieobiektowe elementy języka C++

2. Klasy cz. 2 - Konstruktor kopiujący. Pola tworzone statycznie i dynamicznie - Funkcje zaprzyjaźnione - Składowe statyczne

Szablony funkcji i szablony klas

Typy metod: konstruktory, destruktory, selektory, zapytania, iteratory.

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy WSKAŹNIKI KLASOWE

C++ Przeładowanie operatorów i wzorce w klasach

Rozdział 4 KLASY, OBIEKTY, METODY

1. Które składowe klasa posiada zawsze, niezależnie od tego czy je zdefiniujemy, czy nie?

Standard C++0x (C++1x?) Marcin Świderski

Dziedziczenie jednobazowe, poliformizm

Zaawansowane programowanie w C++ (PCP)

Klasa jest nowym typem danych zdefiniowanym przez użytkownika. Najprostsza klasa jest po prostu strukturą, np

Wskaźniki. nie są konieczne, ale dają językowi siłę i elastyczność są języki w których nie używa się wskaźników typ wskaźnikowy typ pochodny:

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy PRAWA PRZYJACIÓŁ KLASY. Dostęp z zewnątrz: Dostęp z wewnątrz:

Wyliczanie wyrażenia obiekty tymczasowe

Wykład 5: Klasy cz. 3

Wykład 3 Składnia języka C# (cz. 2)

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

PROE wykład 9 C++11, rzutowanie, optymalizacja. dr inż. Jacek Naruniec

Wskaźniki i dynamiczna alokacja pamięci. Spotkanie 4. Wskaźniki. Dynamiczna alokacja pamięci. Przykłady

Materiał Typy zmiennych Instrukcje warunkowe Pętle Tablice statyczne Wskaźniki Tablice dynamiczne Referencje Funkcje

C++ - polimorfizm. C++ - polimorfizm. C++ - polimorfizm. C++ - polimorfizm. C++ - polimorfizm POLIMORFIZM

Instrukcja do pracowni specjalistycznej z przedmiotu. Obiektowe programowanie aplikacji

Funkcje przeciążone, konstruktory kopiujące, argumenty domyślne

Programowanie w C++ Wykład 12. Katarzyna Grzelak. 28 maja K.Grzelak (Wykład 12) Programowanie w C++ 1 / 27

Szablony funkcji i klas (templates)

Języki i techniki programowania Ćwiczenia 2

DYNAMICZNE PRZYDZIELANIE PAMIECI

Programowanie obiektowe i C++ dla matematyków

Wstęp do programowania obiektowego. Wykład 2

Programowanie obiektowe, wykład nr 7. Przegląd typów strukturalnych - klasy i obiekty - c.d.

JAVA. Java jest wszechstronnym językiem programowania, zorientowanym. apletów oraz samodzielnych aplikacji.

Podstawy Programowania Obiektowego

Struktura programu. Projekty złożone składają się zwykłe z różnych plików. Zawartość każdego pliku programista wyznacza zgodnie z jego przeznaczeniem.

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Wprowadzenie w dziedziczenie. Klasa D dziedziczy klasę B: Klasa B klasa bazowa (base class), klasa D klasa pochodna (derived class).

Zaawansowane programowanie w języku C++ Przeciążanie operatorów

Zaawansowane programowanie w języku C++ Programowanie obiektowe

Programowanie w C++ Wykład 11. Katarzyna Grzelak. 13 maja K.Grzelak (Wykład 11) Programowanie w C++ 1 / 30

Programowanie w C++ Wykład 5. Katarzyna Grzelak. 26 marca kwietnia K.Grzelak (Wykład 1) Programowanie w C++ 1 / 40

Programowanie obiektowe i C++ dla matematyków

Wykład 1. Program przedmiotu. Programowanie Obiektowe (język C++) Literatura. Program przedmiotu c.d.:

Programowanie obiektowe Wykład 6. Dariusz Wardowski. dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/14

Wstęp do Programowania 2

Laboratorium 03: Podstawowe konstrukcje w języku Java [2h]

Kurs programowania. Wstęp - wykład 0. Wojciech Macyna. 22 lutego 2016

Zaawansowane programowanie w C++ (PCP)

Transkrypt:

Nowoczesny C++ Rafał Wasilewski 1 1 Wydział Inżynierii Mechanicznej i Informatyki Kierunek informatyka, Rok III Politechnika Częstochowska {wasilewski.rafael@gmail.com 1 Wstęp Streszczenie Tematem pracy jest przedstawienie wybranych elementów języka c++, które weszły do standardu języka C++11. Język c++ jest niewątpliwie jednym z najpopularniejszym z języków obiektowych. Ciągły rozwój tego języka przyczynia się do jego popularyzacji, a standaryzacja dostarcza mechanizmów pozwalających wykorzystywać jednolite wzorce. Standard C++11 rozszerza język c++ o obsługę wielowątkowości oraz jednolite inicjowanie za pomocą list inicjacyjnych, a wprowadzenie semantyki przeniesienia wpływa na wydajność programów. Obecnie język C++ jest jednym z najważniejszym a zarazem najczęściej stosowanych języków programowania na świecie. Wpływ na ten stan ma fakt, iż jest on bardzo elastyczny. Wykorzystywany jest do tworzenia różnego rodzaju programów, gier, aplikacji naukowych oraz sterowników urządzeń. C++ jest językiem szybkim, wydajnym oraz przenośnym. Wartości te zostały odziedziczone z języka C. Dzięki metodyce programowania obiektowego zapanowanie nad złożonością kodu programu jest prostsze. Stosowanie szablonów w języku C++ daje możliwość wykorzystania metodologii programowania uogólnionego. Połączenie tych trzech aspektów sprawia, że C++ jest bardzo silnym językiem programowania. Komitet standaryzacyjny języka C++ w roku 2011 opublikował nowy standard, wprowadzając wiele zmian w języku oraz bibliotece. Zmiany wprowadzone w standardzie oznaczonym jako C++11 lub C++x0 mają na celu ułatwienie pracy oraz zwiększenie efektywności programistów. Aby móc korzystać z nowego standardu należy dodać do kompilatora parametr -std=c++0x. 1

2 Semantyka przeniesienia i referencje r-wartościowe Standard C++11 wprowadza nowy typ referencyjny &&. Jest to referencja do obiektów r-wartości. Obiekty r-wartości to obiekty tymczasowe, literały stałych, funkcje zwracające wartość a nie referencję, wyrażenia typu: x + y, mogące występować po prawej stronie operatora przypisania, a jednocześnie takie do których nie da się użyć operatora pobrania adresu. np.: int x = 852; int& y = 951; // nie zostanie skompilowane, 951 nie jest l-wartością. int&& z = 475; // zostanie skompilowane, 475 jest r-wartością int&& w = x; // nie zostanie skompilowane const int& g= 357; // ok void print(string const& napis); print( Witaj świecie ); Przykład ten jest odstępstwem wprowadzonym przed zaimplementowaniem mechanizmów referencji do r-wartości. Umożliwia on przekazanie zmiennej tymczasowej do funkcji oczekującej referencji. Ponieważ jest to typ referencji do stałej, nie ma możliwości zmiany jego wartości. Obiekty typu && mogą być akceptowane jako wartość nie-stała, umożliwiając funkcjom ich modyfikację. Stosowanie techniki przeciążenia funkcji do określenia czy parametr jest l-wartością czy r-wartością jest podstawą semantyki przenoszenia danych (ang. move semantic). Semantyka przeniesienia nie przenosi obiektu a jedynie jego referencję. Wykorzystanie semantyki przeniesienia wymusza użycie mechanizmu informującego kompilator kiedy należy zrobić pełną głęboką kopię obiektu, a kiedy jest to niepotrzebne. Do tego celu służą r-wartościowe referencje. Klasyczny konstruktor kopiujący wykonuję kopię obiektu, a jako parametr zwraca referencję do l-wartości (const&). vector<string> napisvector; // kod tworzący wektor 10000 łańcuchów znakowych, po 1000 znaków każdy vector<string> svectorcopy(svector); Nowy standard C++11 wprowadza drugi nowy typ konstruktora kopiującego, nazywany konstruktorem przenoszącym (ang. move constructor). Przeprowadza on operacje na r-wartościowej referencji, mogącej odwoływać się do argumentów r-wartościowych. vector<string>maiuscula(const vector<string>& wektornapis){ vector<string> tmp; // tu kod składujący w tmp zawartość z wektornapis pisaną wielkimi literami return tmp; vector<string> svectoropy2(maiuscula(svector)); // r-wartość Mechanizm konstruktora kopiującego dokonuje oczywiście głębokiej kopii obiektu. Natomiast w konstruktorze przenoszącym mechanizm ten został zoptymalizowany jedynie do przeniesienia zawartości obiektu do innego obiektu. Wcześniejszy przykład doskonale obrazuje działanie konstruktora przenoszącego. Jak widać, przenosi on jedynie referencję do obiektu r-wartości zamiast dokonywać 2

zbędnego kopiowania 10000000 znaków do nowego miejsca, tylko po to, aby za chwilę zwolnić oryginalny kontener. Aby modyfikacja obiektu źródłowego była możliwa, r-wartościowa referencja przekazana przez parametr nie może być typu stałego. class Przyklad{ int ileelementow; // liczba elementów char* wdane; // wskaźnik do danych public:... Przyklad(const Przyklad & p); // zwyczajny konstruktor kopiujący Przyklad( Przyklad && p); // konstruktor przenoszenia... ; Przyklad::Przyklad(Przyklad&& objekt): ileelementow(objekt.ileelementow ){ wdane = objekt.wdane ; // przechwycenie adresu objekt.pc = nullptr; //stary obiekt otrzymuje nic w zamian objekt.ileelementow = 0 ; W powyższym przykładzie konstruktor przenoszący wskaźnikowi wdane przypisuje adres wskaźnika objekt.wdane. W tym momencie wdane jak i objekt.wdane wskazują na te same dane. Stwarza to potencjalne zagrożenie dla programu w momencie wywołania destruktorów, gdyż program nie powinien więcej niż raz dla tego samego obszaru pamięci wywołać operatora delete[]. By się przed tym uchronić wskaźnik do danych w obiekcie źródłowym objekt.wdane jest zerowany za pomocą nullptr, dzięki czemu unika się niedozwolonej dealokacji pamięci. Wywołanie operatora zwalniającego pamięć dla wskaźnika pokazującego na NULL jest dozwolone. Wykorzystanie konstruktora przenoszącego zapobiega wielu nadmiarowym operacjom alokacji pamięci przez obiekt. Zdarza się, że kompilator dokonuje własnej optymalizacji kodu. Ważne jest, aby program wykonał się w taki sposób, w jaki została zaimplementowana jego logika. Przykładem takiego kompilatora jest g++ który potrafi dokonać takiej optymalizacji nawet jeżeli konstruktor przenoszący nie jest zdefiniowany. Semantyka przeniesienia jest dozwolona dzięki zastosowaniu r-wartościowych referencji, lecz jej nie gwarantuje. Aby poinformować kompilator o przypadku stosowania semantyki przeniesienia, niezbędne jest adekwatne użycie referencji r-wartościowych: Przyklad test2 = test1; Przyklad test4 (test1 +test3) ; // pasuje do Przyklad::Przyklad(const Przyklad &) // pasuje do Przyklad::Przyklad( Przyklad &&) Reasumując: inicjalizacja obiektów l-wartościami odbywa się za pomocą konstruktora kopiującego, natomiast inicjalizacja obiektów r-wartościowych odbywa się za przy użyciu konstruktora przypisania. Konstruktory te mogą mieć zdefiniowaną całkowicie różną implementację. W podobny sposób powinno się rozważać operacje przypisania. Mechanizm operatora przypisania w wersji przenoszącej w pierwszej kolejności czyści dane obiektu docelowego, po to aby móc przypisać do niego dane z obiektu źródłowego. Problem spowodowany wskazywaniem kilku wskaźników na jeden obiekt, został rozwiązany poprzez wyzerowanie adresu źródłowego wskaźnika do danych. 3

Przykłady implementacji operatora przypisania wykorzystującego kopiowanie oraz operatora przypisania stosującego przenoszenie dla klasy Przyklad: Przyklad & Przyklad::operator=(const Przyklad &obj) { if (this == &obj) return *this; delete [] wdane; ileelementow = obj.ileelementow ; wdane = new char [ileelementow ]; for (int i = 0 ; i < n ; ++i) wdane[i] = obj.wdane [i]; return *this; //przypisanie kopiujące Przyklad & Przyklad::operator=( Przyklad && obj) // przypisanie przenoszące { if ( this == &obj) return * this; delete [] wdane; ileelementow = obj.ileelementow ; wdane = obj. wdane; obj. ileelementow = 0; obj. wdane = nullptr; return *this; Chcąc zastosować konstruktor przenoszący bądź operator przypisania przenoszącego dla obiektów l-wartościowych trzeba dokonać ich konwersji na r-wartość. Konwersja ta jest możliwa za pomocą operatora rzutowania static_cast<decltype(arg)&&>(arg) na typ Przyklad&&. Nowy standard C++11 dostarcza łatwy sposób prowadzący do przeniesienia obiektu. Jest to funkcja std::move() zwracająca r-wartościową referencje do obiektu. Przeniesienie odbędzie się pod warunkiem, że obiekt posiada zdefiniowany operator przeniesienia. Deklaracje funkcji move(), forward(), move_if_noexcept(), declval() umożliwiających generowanie referencji do r-wartości znajdują się w pliku nagłówkowym <utility>. Semantyka przeniesienia z referencjami r-wartościowymi jest zaimplementowana w bibliotece STL. Konstruktory przenoszące jak i operatory przypisania przenoszącego znajdują się we wszystkich klasach STL. 3 Nowości w Klasach Standard C++11 wzbogaca grupę specjalnych metod klas o wcześniej wspomniany konstruktor przenoszący oraz operator przypisania przenoszącego. Dodatkowo zwiększa kontrolę nad metodami klasy- teraz jawnie można specjalizować, czy dana metoda specjalna ma pozostać domyślną czy też zostanie zaimplementowana. Jeżeli dla danej klasy nie zdefiniowano żadnego konstruktora, kompilator syntetyzuje konstruktor domyślny. Jeżeli w klasie zdefiniujemy dowolny konstruktor to kompilator już nie utworzy żadnego innego domyślnego konstruktora czy też operatora przypisania. C++11 umożliwia zadeklarowanie metody klasy w sposób jawny jako domyślną metodę. Służy do tego modyfikator =default umieszczony od deklaracji metody. Możemy również zabronić kompilatorowi syntetyzowania danych metod oraz ich użycia. Pomocy w tym celu jest modyfikator =delete, dzięki niemu metoda będzie 4

zadeklarowana jako usunięta. Przed standardem C++11 taki cel osiągało się deklarując metody danej klasy jako funkcje prywatne. Niemniej stosowanie modyfikatora delete jest bardziej czytelne i łatwiejsze. Definicja klasy w C++11 posiada tylko sześć specjalnych metod które mogą być syntetyzowane przez kompilator. Kompilator natomiast może usuwać dowolną metodę w klasie, co może być wykorzystane do zablokowania konwersji pojedynczych metod. class JakasKlasa { ; JakasKlasa obj1; obj1.foo (5); void foo( double ); void foo( int ) = delete; Powyższy przykład pokazuje wywołanie metody foo( ) odpowiadającej wywołaniu metody foo dla typu int. Kompilator znajdzie dopasowanie, oraz odkryje, że metoda foo(int) posiada w swojej definicji modyfikator delete. Wywołanie funkcji usuniętej spowoduje błąd podczas kompilacji. Obrazuje to bardzo ważną cechę metod usuniętych: są one traktowane jako istniejące przez kompilator w momencie dopasowania, natomiast podczas prób wykorzystania są traktowane przeciwnie, jako nieistniejące. C++11 wprowadza mechanizm delegowania konstruktorów. Jego zadaniem jest przede wszystkim zmniejszenie ilości miejsc w których można popełnić trywialne błędy związane z powielaniem kodu. Delegowanie pozwala tworzyć nowe definicje konstruktorów stosując już istniejący konstruktor. Innymi słowy oddelegowuje część zadań danego konstruktora do innego konstruktora. Class DelKonst { int idx; double db; std::string str; public: DelKonst (int idxx, double dbb, std::string strr): idx(idxx), db(dbb), str(strr){ /* */ DelKonst ( ): DelKonst(0, 0.01, Oh ){ /* */ DelKonst (int idxx): DelKonst( idxx, 0.01, Oh ){ /* */ DelKonst (int kk idxx double dbb): DelKonst(idxx, dbb, Oh ){ /* */ 4 Automatyczna deklaracja typów w C++11 Ogromnym udogodnieniem wprowadzonym do języka w standardzie C++11 jest dedukowanie typu zmiennej w oparciu o typ jaki posiada wartość inicjalizująca. Posłużyło do tego słowo kluczowe auto znane z języka C, niemniej wykorzystywane sporadycznie przez programistów. Teraz kompilator przydziela inicjalizowanej zmiennej ten sam typ jaki posiada wartość inicjalizująca. Pozwala to omijać długie i żmudne deklaracje typów. Wystarczy posłużyć się słowem kluczowym auto. auto aintiger = 659; // aintiger jest typu int auto aldouble = 2.7e13L // aldouble jest typu long double 5

Przydatność dedukcji typów jeszcze bardziej zyskuje na znaczeniu podczas pracy z typami złożonymi, między innymi takimi jak w standardowej bibliotece szablonów. std::vector<double>punkty; std::vector<double>::iterator punktywektor = punkty.begin(); // lub auto punktywektor = punkty.begin(); // C++11 analogiczny efekt 5 Jednolita inicjalizacja Od momentu wprowadzenia standardu C++11 możliwe jest stosowanie inicjalizacji wykorzystujących notację klamrową wraz z listą wartości inicjalizujących również dla typów zdefiniowanych przez programistę. Uprzednio możliwe było to tylko dla typów wbudowanych. Możliwe jest stosowanie listy inicjalizującej w wyrażeniach używających operatora new. int * tablicaintow = new int [5] {0,1,9,3,4; // C++11 W miejsce listy argumentów konstruktora dla obiektów klas z powodzeniem można zamiennie wykorzystywać listę w klamrach. Slupek slup1 (4, 11.3); // po staremu Slupek slup2 {8, 92.3; lub Slupek slup3 = {8, 67.23 // C++11 Do standardu C++11 dodano również szablon klas std::initializer_list służący jako parametr konstruktora. Inicjator listy pozwala przekazać zbiór wartości zapisany poprzez argument funkcji, metody bądź konstruktora. Wymagane jest, aby wszystkie elementy posiadały ten sam typ bądź dało się je niejawnie przekonwertować do jednakowego typu. Wszystkie kontenery ze standardowej biblioteki szablonów mają konstruktory przyjmujące argumenty będące szablonem klasy std::initializer_list. Std::vector<int> wektortablicowy {4,3,2; Deklaracja klasy std::initializer_list znajduje się w pliku nagłówkowym <initializer_list>. Klasa ta zawiera metody umożliwiające określenie początku: begin() oraz końca: end() listy. Operandami typu std::initialize_list można posługiwać się w konstruktorach, metodach klas oraz zwykłych funkcjach double sumator (){std::initialize_list<double> ilist { double sum = 0 ; for (auto idx = ilist.begin(); idx!= ilist.end(); idx++ ) sum += *idx; return sum; int main() {... double jakaszmienna = sumator({4.6, 5.2, 3.8);... 6

6 Inteligentne wskaźniki Inteligentne wskaźniki (ang. smart pointers) poza standardowym zachowaniem jakie mają zwykłe wskaźniki, dostarczają dodatkowych możliwości. Język C++11 oferuje trzy nowe klasy inteligentnych wskaźników - unique_ptr, shared_ptr oraz week_ptr. Są one bardzo pomocne podczas pracy z dynamicznymi przydziałami pamięci. Inteligentne wskaźniki auto_ptr, shared_ptr, unique_ptr definiują obiekty zbliżone do wskaźników otrzymanych za pomocą operatora new. Dzięki temu, że inteligentne wskaźniki są obiektami klas, ich definicje zawierają destruktory. Podczas usuwania obiektów inteligentnych wskaźników, ich destruktor za pomocą instrukcji delete zwalnia pamięć. Z tego powodu, jeżeli przypiszemy do takiego wskaźnika adres poprzez instrukcję new, nie musimy się już martwić o zwolnienie pamięci, ponieważ jeżeli nie zrobimy tego sami, zrobi to za nas destruktor w momencie usuwania obiektu inteligentnego wskaźnika. Inteligentne wskaźniki do języka C++11 zaczerpnięte zostały z biblioteki Boost. Klasy inteligentnych wskaźników zadeklarowane są w pliku nagłówkowym <memory>. Unique_ptr (unikalny) jest unikalnym wskaźnikiem na obiekt. W momencie usunięcia wskaźnika obiekt zostanie zniszczony. unique_ptr<string>p3(new string ( auto )); vector<unique_ptr<int>> vp(size); Shared_ptr (współdzielony) jest wskaźnikiem współdzielonym przez wiele wskaźników tego typu. Klasa zawiera zmienną zliczającą wskaźniki wskazujące na obiekt. W momencie gdy ostatni współdzielony wskaźnik zostanie zniszczony, obiekt na który wskazywał również ulegnie zniszczeniu. Week_ptr( słaby) wskazuje na obiekty wskazywane poprzez współdzielone wskaźniki, jednak nie utrzymuje ich przy życiu. W momencie zniszczenia wskaźnika współdzielonego, obiekt na który wskazywał również zostanie zniszczony. Wskaźniki słabe jeżeli wskazywały na taki obiekt zaczną wskazywać na nullptr. 7 Wielowątkowość Niewątpliwie największa nowością w standardzie C++11 jest możliwość wykorzystania wielowątkowości. Wcześniej było to możliwe, lecz wymagało stosowania zewnętrznych bibliotek. Utworzenie nowego wątku jest naprawdę proste: void do_some_work(); std::thread my_thread(do_some_work); W C++11 biblioteka standardowa została wzbogacona o nowy model pamięci przystosowany do przetwarzania wielowątkowego. Dodano klasy zarządzające wątkami, synchronizacją współbieżnych operacji oraz ochroną danych współdzielonych przez wątki. Wprowadzono również niskopoziomowe operacje atomowe będące podstawą synchronizacji wątków. Standard C++11 wspiera współbieżność poprzez mechanizmy zdefiniowane w plikach nagłówkowych wchodzących w skład biblioteki standardowej. Plik <thread> wspiera tworzenie i uruchamianie wątków. Ochrona przed wzajemnym wykluczaniem 7

zdefiniowana jest w pliku nagłówkowym <mutex>, monitory i zmienne warunkowe będące podstawą synchronizacji wątków znajdują się w nagłówkowym pliku <condition_variable>. Operacje wysokopoziomowe, takie jak funkcje przyszłości umożliwiają szablony klas std::future<>, std::shared_future<> z pliku nagłówkowego <future>. W C++11 użycie słowa thread_local definiującego nowy model pamięci, wspiera realizację operacji wielowątkowych. Therad_local definiuje użycie zmiennych jako statyczne względem ustalonego wątku. Ich czas życia jest uzależniony do czasu życia wątku. 8 Podsumowanie W powyższej pracy zostały omówione wybrane elementy wprowadzone wraz ze standardem C++11. Ukierunkowany jest on na usprawnienie pracy programistów poprzez uproszczenie nauki języka oraz zwiększenie możliwości jego zastosowania. Efektywność wykorzystania języka C++ wzrosła poprzez wykorzystanie semantyki r-wartości oraz inteligentnych wskaźników, które pomagają w zarządzaniu obszarami pamięci przydzielonymi dynamicznie. Jedną z istotniejszych zmian jest wprowadzenie do standardowej biblioteki elementów wspierających przetwarzanie współbieżne. W niniejszej pracy omówione zostały kluczowe elementy standardu C++11, jednak na uwagę zasługuje również między innymi obsługa wyrażeń regularnych oraz wyrażenia lambda. Aktualnie nie wszystkie kompilatory wspierają pełną listę dodanych funkcjonalności nowego standardu. Sytuacja ta poprawia się wraz z rozwojem i wydawaniem nowych wersji kompilatorów. Podsumowując standard C++11 znacząco zwiększa przejrzystość i elastyczność języka C++ oraz upraszcza jego elementy. Bibliografia [1] A. Williams, Język C++ i przetwarzanie współbieżne w akcji, Helion 2013. [2] S. Prata, Język C++ Szkoła programowania Wydanie VI, Helion 2013. [3] C++11 FAQ http://www.stroustrup.com/c++11faq.html 8