Dzisiejszy wykład. Klasa string. wersja prosta wersja ze zliczaniem odwołań. Wyjątki Specyfikator volatile Semafory

Podobne dokumenty
Kurs programowania. Wykład 1. Wojciech Macyna. 3 marca 2016

Programowanie obiektowe i C++ dla matematyków

Operacje wejścia/wyjścia (odsłona druga) - pliki

PARADYGMATY PROGRAMOWANIA Wykład 3

Programowanie obiektowe i C++ dla matematyków

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

Jzyk C++ cz 3. Jarosław Gramacki Instytut Informatyki i Elektroniki ( $)*)+' *, - ( ' )*'.' '',*/ *, ','*0) 1 / ) %*+ 2'' 2" ( $%%) )'20 )*0) 1 / )

DANE TEKSTOWE W JĘZYKU C/C++ - TABLICE ZNAKOWE

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

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

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

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

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

ŁAŃCUCHY W JĘZYKU C/C++

Składnia C++ Programowanie Obiektowe Mateusz Cicheński

Programowanie obiektowe w C++ Wykład 12

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

Programowanie obiektowe - Przykładowe zadania egzaminacyjne (2005/2006)

Wstęp do programowania obiektowego. WYKŁAD 3 Dziedziczenie Pola i funkcje statyczne Funkcje zaprzyjaźnione, this

referencje Wykład 2. Programowanie (język C++) Referencje (1) int Num = 50; zdefiniowano zmienną Num (typu int) nadając jej wartość początkową 50.

Obsługa wyjątków. Język C++ WW12

Język C++ wykład VI. uzupełnienie notatek: dr Jerzy Białkowski. Programowanie C/C++ Język C++ wykład VI. dr Jarosław Mederski.

Operatory na rzecz typu TString

Konstruktor kopiujacy

Język C++ wykład VIII

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

Programowanie w języku C++

Kurs programowania. Wykład 3. Wojciech Macyna. 22 marca 2019

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

Wyjątki (exceptions)

Programowanie obiektowe

Wyjątki. Wyjątki. Bogdan Kreczmer. Katedra Cybernetyki i Robotyki Politechnika Wrocławska

Wykład II. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

Wstęp do Programowania 2

Programowanie Obiektowo Zorientowane w języku C++ Klasy, pola, metody

Operator przypisania. Jest czym innym niż konstruktor kopiujący!

EGZAMIN PROGRAMOWANIE II (10 czerwca 2010) pytania i odpowiedzi

ATD. Wykład 8. Programowanie (język C++) abstrakcyjny typ danych. Abstrakcyjne typy danych (ATD) Metody czysto wirtualne. Definicje i uwagi:

PARADYGMATY PROGRAMOWANIA Wykład 4

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

Tablice deklaracja, reprezentacja wewnętrzna

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

Podstawy programowania w języku C++

Języki programowania - podstawy

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

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

Składnia C++ Programowanie Obiektowe Mateusz Cicheński

Podstawy programowania w języku C++

PARADYGMATY PROGRAMOWANIA Wykład 2

Operacje wejścia/wyjścia odsłona pierwsza

tablica: dane_liczbowe

Język C++ Różnice między C a C++

Wstęp do Programowania 2

Dzisiejszy wykład. Wzorce funkcji Wzorce klas Tablica asocjacyjna Składowe statyczne

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

Programowanie Obiektowe i C++

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

Podstawy Programowania Obiektowego

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

C-struktury wykład. Dorota Pylak

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:

Wykład 4: Klasy i Metody

Programowanie 2. Język C++. Wykład 3.

w odróżnieniu od procesów współdzielą przestrzeń adresową mogą komunikować się za pomocą zmiennych globalnych

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

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

Języki programowania. Przetwarzanie tablic znaków. Część druga. Autorzy Tomasz Xięski Roman Simiński

Rzutowanie i konwersje

PROGRAMOWANIE OBIEKTOWE W C++ cz. 2. Dziedziczenie, operacje wej cia-wyj cia, przeładowanie operatorów.

Podstawy programowania

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

wykład IV uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C, a C++. wykład IV dr Jarosław Mederski Spis Język C++ - wstęp

KURS C/C++ WYKŁAD 8. Deklaracja funkcji informuje komplilator jaką wartość funkcja będzie zwracała i jakiego typu są jej argumenty.

Temat: Dynamiczne przydzielanie i zwalnianie pamięci. Struktura listy operacje wstawiania, wyszukiwania oraz usuwania danych.

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

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

Informatyka. Wy-08 Klasy. mgr inż. Krzysztof Kołodziejczyk

Tbli Tablice obiektów biktó są tworzone dokładnie d tak samo, jak i tablice, składające się z elementów innego typu

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

Referencje do zmiennych i obiektów

Efekty uboczne błędów

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

Algorytmy i złożoności. Wykład 3. Listy jednokierunkowe

Lista dwukierunkowa - przykład implementacji destruktorów

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

Wskaźniki w C. Anna Gogolińska

Szablon klasy std::vector

int tab[5]; tab[1]; ciągły obszar pamięci, w którym umieszczone są elementy tego samego typu macierz [ ] - dwuargumentowy operator indeksowania

Hermetyzacja oraz pola i metody statyczne

Ćwiczenie 7 z Podstaw programowania. Język C++, programy pisane w nieobiektowym stylu programowania. Zofia Kruczkiewicz

Programowanie Obiektowew języku C++ Zadania L4

Programowanie obiektowe

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

Lab 9 Podstawy Programowania

Kurs programowania. Wykład 9. Wojciech Macyna. 28 kwiecień 2016

Do czego służą klasy?

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

Programowanie obiektowe i C++ dla matematyków

Programowanie w C++ Wykład 8. Katarzyna Grzelak. 15 kwietnia K.Grzelak (Wykład 8) Programowanie w C++ 1 / 33

Transkrypt:

Dzisiejszy wykład Klasa string wersja prosta wersja ze zliczaniem odwołań Wyjątki Specyfikator volatile Semafory 1

Klasa string Przetwarzanie tekstów jest powszechną dziedziną zastosowań komputerów W języku C i C++ brak prawdziwego wbudowanego typu łańcuchowego, char* jest trudny w użyciu i podatny na błędy class mystring char *dane; public: mystring (); ~mystring (); mystring (const char *s); unsigned int length () const; mystring (const mystring & src); Referencja mystring & operator= (const mystring & src); mystring & operator+= (const mystring & src); char operator[] (unsigned int i) const; char &operator[] (unsigned int i); Brak referencji friend ostream & operator<< (ostream & o, const mystring & s); inline mystring operator+ (const mystring & s1, const mystring & s2); 2

Klasa string - konstruktor i lista inicjacyjna Bez użycia listy inicjacyjnej mystring () dane = NULL; Z użyciem listy inicjacyjnej mystring ():dane (NULL) W tym przypadku nie ma żadnej różnicy. Różnica pojawia się, jeżeli pola posiadają konstruktory Bez listy inicjacyjnej: wywołany konstruktor bezparametrowy, a następnie operator przypisania Z listą inicjacyjną: wywołany konstruktor z parametrem Zastosowanie inicjalizacji pól obiektowych klasy skraca program i przyspiesza jego wykonanie 3

Klasa string - operator + Specyfikator friend nie jest potrzebny, funkcja korzysta wyłącznie ze składowych publicznych klasy string Podczas zwracania wartości z funkcji zostanie użyty konstruktor kopiujący inline mystring operator+ (const mystring & s1, const mystring & s2) mystring s (s1); return s += s2; 4

Klasa string - operator char* W klasie można zdefiniować operatory konwersji do innego typu Często użyteczne w przypadku wykorzystywania funkcji przyjmujących typy wbudowane w język (np. char*) mystring::operator char*() if(!dane) dane=new char[1]; dane[0]='\0'; return dane; W klasie string mozliwość kolizji z operatorem indeksowania mystring s; s[0]='a'; //s.operator[](0) or (s.operator char*())[0]? 5

Wyjątki Poprawny program sprawdza kody błędów int fun() //... fd=open("file",o_rdwr); if(fd==-1) return -1; if(read(fb,buffer,15)!=15) return -1; if(write(fd,buffer,4)!=4) return -1; //... return 0; Sprawdzanie kodów błędów za każdym razem jest nużące i łatwo o nim zapomnieć W niektórych przypadkach trudno jest zwrócić kod błędu, np. atoi() może zwrócić dowolną liczbę całkowitą i nie ma wartości, która może sygnalizować błąd Zwracanie błędów z konstruktorów obiektów jest utrudnione 6

Wyjątki Język C++ dostarcza nowy mechanizm zgłaszania błędów: wyjątki class myexception void f1() if(...) throw myexception(); void f2() f1(); int main() try f2(); catch(myexception&) cout << "myxception caught"<<endl; return 0; Klasa wyjątku, umożliwiająca rozróżnienie błędów Zgłoszenie błędu Wykrycie błędu 7

Wyjątki Rozróżnienie błędów następuje na podstawie typu zgłaszanego wyjątku class bad_index class no_memory void f1() if(...) throw bad_index(); if(...) throw no_memory(); //... try f2(); catch(bad_index&) //... catch (no_memory&) //... Operator new zgłasza wyjątek bad_alloc w przypadku braku pamięci 8

Wyjątki Podczas zgłaszania wyjątku wywoływane są destruktory wszystkich lokalnych obiektów na drodze od funkcji wywoływanej do wywołującej #include <iostream> using namespace std; class myexception class tester string name; public: tester(const string& n): name(n) cout<<name<<"()"<<endl; ~tester() cout<<"~"<<name<<"()"<<endl; void f1() tester f1("f1"); throw myexception(); cout << "Exiting f1"<<endl; void f2() tester f2("f2"); f1(); cout << "Exiting f2"<<endl; int main() tester main("main"); f2(); return 0; 9

Wyjątki Jeżeli nie ma odpowiedniej instrukcji catch, wykonywanie programu jest przerywane Możemy zmodyfikować klasę string tak, aby zgłaszała wyjątki class mystring char *dane; public: class index_out_of_range //... char operator[] (unsigned int i) const if (!dane) throw index_out_of_range(); if (i >= strlen (dane)) throw index_out_of_range(); return dane[i]; 10

Problemy z wyjątkami Nieuważne stosowanie wyjątków może prowadzić do wycieku zasobów lub niespójności danych void fun() char* a = new char[1024]; char* b = new char[1024]; //... delete [] a; delete [] b; Jeżeli new zgłosi wyjątek, obszar zaalokowany dla zmiennej a nie zostanie zwolniony void fun() char* a = NULL, *b=null; try a = new char[1024]; b = new char[1024]; //... catch (...) delete [] a; delete [] b; throw; delete [] a; delete [] b; Metoda naprawienia błędu, poprawna ale nie najlepsza 11

Problemy z wyjątkami Nieuważne stosowanie wyjątków może prowadzić do wycieku zasobów lub niespójności danych mystring & operator= (const mystring & src) if (this!= &src) delete[]dane; if (src.dane) dane = new char [strlen(src.dane) + 1]; strcpy (dane, src.dane); else dane = 0; Jeżeli new zgłosi return *this; wyjątek, zawartość łańcucha zostanie utracona, a dane będzie miała nieprawidłową wartość, co spowoduje problemy w destruktorze mystring & operator= (const mystring & src) if (this!= &src) char* nowedane; if (src.dane) nowedane = new char [strlen (src.dane) + 1]; strcpy (nowedane, src.dane); else nowedane = 0; delete [] dane; dane=nowedane; return *this; Poprawiona wersja nie niszczy łańcucha w przypadku braku pamięci 12

Klasa string - implementacja ze zliczaniem odwołań Kopiowanie łańcucha tekstowego jest operacją dość kosztowną Łańcuchy tekstowe często przesyłane są przez wartość Szukamy sposobu implementacji, która zmniejszy liczbę alokacji pamięci i kopiowań Rozwiązaniem jest zastosowanie zliczania odwołań 13

Klasa string - implementacja ze zliczaniem odwołań Klasa jest jedynie uchwytem - zawiera wskaźnik do rzeczywistej implementacji łańcucha class string struct rctext; rctext* data; public: string(char* s); string& operator= (const string&); ~string();... struct string::rctext char* s; unsigned int size; unsigned int n;... string s1("ala"); s1 data s size=3 n=1 ala\0 14

Klasa string - implementacja ze zliczaniem odwołań Kopiowanie łańcucha kopiuje wskaźnik do wewnętrznej reprezentacji i zwiększa licznik odwołań class string struct rctext; rctext* data; public: string(char* s); string& operator= (const string&); ~string();... struct string::rctext char* s; unsigned int size; unsigned int n;... string s1("ala"); string s2=s1; s1 data s2 data s size=3 n=2 ala\0 15

Klasa string - implementacja ze zliczaniem odwołań Modyfikacja jednej z kopii łańcucha powoduje rozdzielenie s1 i s2 class string public: char read (unsigned int i) const; void write (unsigned int i, char c);... s1 data s size=3 n=1 ala\0 string s1("ala"); string s2=s1; s2.write(0,'o'); s2 data s size=3 n=1 ola\0 16

Klasa string - implementacja ze zliczaniem odwołań Chcemy, żeby operator indeksowania działał poprawnie dla zapisu i odczytu class string... string s1("ala"); string s2=s1; char a=s2[0]; s2[0]='o'; Nie chcemy, aby odczyt znaku powodował wykonanie kopii łańcucha Możemy to osiągnąć poprzez zwracanie przez operator indeksowania nie referencji do znaku, ale specjalnej klasy Cref 17

Klasa string - implementacja ze zliczaniem odwołań Klasa Cref zachowuje się jak char, ale umożliwia rozróżnienie pisania i czytania class string public: string(char* s); string& operator=(const string&); ~string(); void check(unsigned int i) const; Cref operator[](unsigned int i); char operator[](unsigned int i) const; char string::read(unsigned int i) const; void string::write(unsigned int i, char c) data = data->detach(); data->s[i] = c;... string::cref string::operator[](unsigned int i) check(i); return Cref(*this,i); class string::cref friend class string; string& s; unsigned int i; Cref (string& ss, unsigned int ii) :s(ss), i(ii) public: operator char() const return s.read(i); string::cref& operator = (char c) s.write(i,c); return *this; string::cref& operator = (const Cref& ref) return operator= ((char)ref); 18

rcstring i wielowątkowość Implementacja ze zliczaniem odwołań może powodować problemy w programach wielowątkowych #include <stdio.h> #include <pthread.h> #include "rcstring.h" rcstring s ("ala"); void * thread1 (void *p) for (unsigned int i = 0; i < 100000; i++) rcstring s1 (s); pthread_exit (p); void * thread2 (void *p) for (unsigned int i = 0; i < 100000; i++) rcstring s1 (s); pthread_exit (p); int main () pthread_t t1; pthread_t t2; pthread_create (&t1, NULL, thread1, NULL); pthread_create (&t2, NULL, thread2, NULL); pthread_join (t1, (void **) &retval1); pthread_join (t2, (void **) &retval2); printf ("RefCount=%d\n", s.getrefcount ()); inline rcstring::rcstring(const rcstring& x) x.data->n++; data=x.data; inline rcstring::~rcstring() if(--data->n==0) delete data; jednocześnie Dwa wątki mogą zmieniać wartość n 19

rcstring i wielowątkowość Operacja "n++" nie jest operacją niepodzielną Składa się z trzech faz: Pobranie wartości z pamięci Zwiększenie wartości Wpisanie wartości do pamięci Te operacje mogą się przeplatać w kilku wątkach W efekcie zmienna ma niewłaściwą wartość końcową (zwiększenie o jeden, zamiast o dwa) thread1: d0=n; thread2: d0=n; thread1: d0=d0+1; thread2: d0=d0+1; thread1: n=d0; thread2: n=d0; Konieczność stosowania obiektów synchronizacyjnych (semaforów) lub specjalnych instrukcji asemblera 20

Specyfikator volatile Specyfikator volatile oznacza, że wartość zmiennej może zmieniać się poza kontrolą programu i w związku z tym zabrania optymalizacji odnoszących się do tej zmiennej (np. przechowywania w rejestrach) Używana, kiedy odwołania do zmiennej są odwołaniami do rejestrów urządzeń wejścia/wyjścia Niestety, nie pomoże nam w przypadku łańcucha ze zliczaniem odwołań 21

Specyfikator volatile Dodanie specyfikatora volatile spowoduje, że program zakończy się zgodnie z naszymi oczekiwaniami To jedynie ilustracja - użycie volatile do synchronizacji pamięci między wątkami nie jest poprawne #include <stdio.h> #include <pthread.h> int val = 0; void * fun1 (void *) val = 0; while (1) if (val!= 0) break; printf ("wyszlismy z petli\n"); pthread_exit (NULL); int main () pthread_t w; pthread_create (&w, NULL, fun1, NULL); val = 1; pthread_join (w, NULL); #include <stdio.h> #include <pthread.h> volatile int val = 0; void * fun1 (void *) val = 0; while (1) if (val!= 0) break; printf ("wyszlismy z petli\n"); pthread_exit (NULL); int main () pthread_t w; pthread_create (&w, NULL, fun1, NULL); val = 1; pthread_join (w, NULL); 22

Semafory struct rcstring::rctext char *s; unsigned int size; unsigned int n; pthread_mutex_t mutex; rctext (unsigned int nsize, const char *p) n = 1; size = nsize; s = new char[size + 1]; strncpy (s, p, size); s[size] = '\0'; pthread_mutex_init (&mutex, NULL); unsigned int AtomicIncrement() pthread_mutex_lock(&mutex); unsigned int retval=n++; pthread_mutex_unlock(&mutex); return retval; unsigned int AtomicDecrement() pthread_mutex_lock(&mutex); unsigned int retval=n--; pthread_mutex_unlock(&mutex); return retval; //... data->n++ Sekcja krytyczna 23