Języki programowania

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

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

ZASADY PROGRAMOWANIA KOMPUTERÓW

Programowanie obiektowe C++

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

Programowanie w C++ Wykład 5. Katarzyna Grzelak. 16 kwietnia K.Grzelak (Wykład 1) Programowanie w C++ 1 / 27

Lab 9 Podstawy Programowania

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

Język C++ wykład VIII

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 I. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

Wykład 8: klasy cz. 4

Podstawy programowania. Wykład 6 Wskaźniki. Krzysztof Banaś Podstawy programowania 1

Programowanie w języku C++

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

Programowanie i struktury danych

Programowanie obiektowe C++

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

Wskaźniki. Informatyka

> C++ dynamiczna alokacja/rezerwacja/przydział pamięci. Dane: Iwona Polak. Uniwersytet Śląski Instytut Informatyki

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

Programowanie komputerowe. Zajęcia 5

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

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

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

DYNAMICZNE PRZYDZIELANIE PAMIECI

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

STL: Lekcja 1&2. Filozofia STL

1 Wskaźniki. 1.1 Główne zastosowania wskaźników

Programowanie obiektowe w C++ Wykład 1

Programowanie, część I

Podstawy informatyki. Elektrotechnika I rok. Język C++ Operacje na danych - wskaźniki Instrukcja do ćwiczenia

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

Co to jest sterta? Sterta (ang. heap) to obszar pamięci udostępniany przez system operacyjny wszystkim działającym programom (procesom).

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

Programowanie obiektowe w C++ Wykład 12

Wstęp do informatyki- wykład 12 Funkcje (przekazywanie parametrów przez wartość i zmienną)

Podstawy Informatyki. Inżynieria Ciepła, I rok. Wykład 10 Kurs C++

Szablon klasy std::vector

Programowanie w C++ Wykład 8. Katarzyna Grzelak. 7 maja K.Grzelak (Wykład 8) Programowanie w C++ 1 / 31

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

Podstawy programowania obiektowego

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

Podstawy programowania w języku C++

Wykład 5: Klasy cz. 3

Techniki Programowania wskaźniki

Programowanie w C++ Wykład 6. Katarzyna Grzelak. 1 kwietnia K.Grzelak (Wykład 6) Programowanie w C++ 1 / 43

Podstawy Programowania

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

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

TEMAT : KLASY DZIEDZICZENIE

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

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

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

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

Programowanie w C++ Wykład 14. Katarzyna Grzelak. 3 czerwca K.Grzelak (Wykład 14) Programowanie w C++ 1 / 27

Podstawy algorytmiki i programowania - wykład 4 C-struktury

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

Część 4 życie programu

Wykład 4: Klasy i Metody

Aby uzyskać zaliczenie w pierwszym terminie (do 30 stycznia 2018) rozliczyć trzeba co najmniej 8 projektów, po 4 z każdej z części: C++ oraz Python.

TABLICE W JĘZYKU C/C++ typ_elementu nazwa_tablicy [wymiar_1][wymiar_2]... [wymiar_n] ;

// Liczy srednie w wierszach i kolumnach tablicy "dwuwymiarowej" // Elementy tablicy są generowane losowo #include <stdio.h> #include <stdlib.

Wykład 1: Wskaźniki i zmienne dynamiczne

typ y y p y z łoż o on o e n - tab a lice c e w iel e owym m ar a o r we, e stru r kt k ury

KURS C/C++ WYKŁAD 6. Wskaźniki

Programowanie obiektowe C++

Zaawansowane programowanie w języku C++ Biblioteka standardowa

Wstęp do programowania

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

tablica: dane_liczbowe

1 Wskaźniki i zmienne dynamiczne, instrukcja przed zajęciami

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

Podstawy programowania. Wykład: 6. Tablice statyczne. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

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

Podstawy programowania w języku C++

PARADYGMATY PROGRAMOWANIA Wykład 4

Podstawy informatyki. Informatyka stosowana - studia niestacjonarne. Grzegorz Smyk. Wydział Inżynierii Metali i Informatyki Przemysłowej

Języki i metodyka programowania. Wskaźniki i tablice.

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

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

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

Szablony funkcji i szablony klas

JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Wykład 6

KARTA PRZEDMIOTU. Egzamin / zaliczenie. Egzamin / zaliczenie. ocenę*

Podstawowe elementy proceduralne w C++ Program i wyjście. Zmienne i arytmetyka. Wskaźniki i tablice. Testy i pętle. Funkcje.

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

Wstęp do programowania

Zajęcia nr 5 Algorytmy i wskaźniki. dr inż. Łukasz Graczykowski mgr inż. Leszek Kosarzewski Wydział Fizyki Politechniki Warszawskiej

Wstęp do programowania. Wykład 1

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

PARADYGMATY PROGRAMOWANIA Wykład 3

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

Konstruktor kopiujacy

Szablony klas, zastosowanie szablonów w programach

Podstawy języka C++ Maciej Trzebiński. Instytut Fizyki Jądrowej Polskiej Akademii Nauk. Praktyki studenckie na LHC IVedycja,2016r.

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

Laboratorium nr 9. Temat: Wskaźniki, referencje, dynamiczny przydział pamięci, tablice dynamiczne. Zakres laboratorium:

I - Microsoft Visual Studio C++

Programowanie - wykład 4

Transkrypt:

Języki programowania Nowoczesne techniki programowania Wykład 6 Witold Dyrka witold.dyrka@pwr.wroc.pl 11/01/2012

Prawa autorskie Slajdy do dzisiejszego wykładu powstały w oparciu o: C++ Language Tutorial (Juan Soulié) http://www.cplusplus.com/doc/tutorial/ slajdy Bjarne Stroustrupa do kursu Foundations of Engineering II (C++) prowadzonego w Texas A&M University http://www.stroustrup.com/programming

Materiały Literatura Bjarne Stroustrup. Programowanie: Teoria i praktyka z wykorzystaniem C++. Helion (2010) Jerzy Grębosz. Symfonia C++ standard. Edition 2000 (2008) Dowolny podręcznik języka C++ w standardzie ISO 98 www.cplusplus.com - The C++ Reference Network (j.ang.) Środowisko programistyczne Microsoft Visual C++ (rekomendowane) Dowolne środowisko korzystające z GCC

Program wykładów 1. Pierwszy program. Obiekty, typy i wartości 2. Wykonywanie obliczeń. Błędy 3. Pisanie i wykańczanie programu 4. Techniki pisania funkcji i klas 5. Strumienie wejścia/wyjścia 6. Wskaźniki i tablice 7. Systematyka technik i języków programowania* * nie zdążymy:-(

Zagadnienia Tablice tworzenie, inicjacja, przekazywanie do funkcji Wskaźniki operatory adresu i deferencji arytmetyka wskaźników Tworzenie obiektów i tablic w pamięci wolnej Tablica czy wektor?

Tablice Tablica jest szeregiem elementów tego samego typu umieszczonych w ciągłym bloku pamięci typ_elementu nazwa_tablicy[liczba_elementów] np. int wiek[7] wiek: 0 sizeof(int) 1 2 3 4 5 elementy tablicy są indeksowane od zera 6

Dostęp do elementów tablicy nazwa_tablicy [indeks_elementu] np. wiek: 23 30 56 71 25 32 45 0 1 2 3 4 5 6 cout << wiek[0]; cout << wiek[6]; cout << wiek[7]; cout << wiek[-1]; wiek[0] = 25; wiek[1] = wiek[6]; wiek[7] = 26; // 23 // 45 //?? wartość nieokreślona // jednak kompilator nie zgłosi błędu // może powodować błąd czasu wykonania // bzdura, która się kompiluje // podstawiamy wartość 25 na pierwszą pozycję w tabeli // podstawiamy wartość 2-gą wartością z pozycji 7-mej // zapisujemy 26 poza obszarem zarezerwowanym // dla tablicy wiek możemy nadpisać inną zmienną // jednak kompilator nie zgłosi błędu // może powodować błąd czasu wykonania

Tworzenie tablicy Standardowa tablica ma z góry określoną liczbę elementów, na które kompilator rezerwuje pamięć rozmiar tablicy musi być określony przez literał stały void f(int n) { int tablica_calk[60]; } // ok const int rozmiar = 20; char tablica_znak[rozmiar]; // ok double tablica_rzeczyw[n]; // błąd kompilacji int liczba_el = 10; double tablica[liczba_el]; // błąd kompilacji //...

Inicjacja tablicy w zakresie globalnym: automatyczna inicjacją wartością domyślną dla typu elementów int wiek[5]; int main() { cout << wiek[2]; } // wyświetli: 0 w zakresie lokalnym (np. w funkcji) brak inicjacji int main() { int wiek[5]; cout << wiek[2]; } // wyświetli: nie-wiadomo-co!

Lista inicjacyjna tablicy int wiek[7] = { 23, 30, 56, 71, 25, 32, 45 }; wiek: 23 30 56 71 25 32 45 71 25 0 0 int wiek[7] = { 23, 30, 56, 71, 25 }; wiek: 23 30 56 int wiek[] = { 23, 30, 56, 71, 25, 32 }; wiek: 23 30 56 71 25 32 0 0 0 0 0 int wiek[6] = { }; wiek: 0

Lista inicjacyjna tablicy znaków char imie[6] = { 'W', 'i', 't', 'o', 'l', 'd' }; imie: 'W' 'i' 't' char imie[6] = ''Witold''; 'o' 'l' 'd' // błąd kompilacji! Wyraz nie mieści się w tablicy char imie[] = ''Witold''; imie: 'W' 'i' 't' 'o' 'l' 'd' 0 // C-string, czyli // ciąg ASCIIZ //... imie = ''Janusz''; // błąd kompilacji! W ten sposób można tylko inicjować tablice

Tablice wielowymiarowe Tablice wielowymiarowe są jakby tablicami tablic const int wymiar_n = 10; const int wymiar_m = 20; int main() { int macierz[wymiar_n][wymiar_m]; for (n=0;n<wymiar_n;n++) for (m=0;m<wymiar_m;m++) { macierz[n][m]=(n+1)*(m+1); } double wiek[100][365][24][60][60]; return 0; } // liczba wymiarów nie jest ograniczona, // ale pamięć tak: standardowo // ta tablica zajmie ponad 25 gigabajtów

Przekazywanie tablic jako parametrów funkcji Nie da się przekazać tablicy przez wartość Przekazujemy adres bloku pamięci zajętego przez tablicę void drukuj(double tablica[]) adres tablicy określa jej nazwa: double tablica1[50]; drukuj(tablica1); tablica nie pamięta swojego rozmiaru trzeba go przekazać osobno: void drukuj (double tablica[], int rozmiar) { for (int i=0; i<rozmiar; i++) cout << tablica[i] << endl; } int main () { double pierwsza[] = {1.2, 3.4, 5.6}; double druga[] = {2.1, 4.3, 6.5, 8.7, 10.9}; drukuj(pierwsza, 3); drukuj(druga, 5); return 0; }

Przekazywanie tablic wielowymiarowych jako parametrów funkcji Kompilator musi wiedzieć czy blok pamięci o pojemności np. 200 elementów ma traktować jako tablicę 10x10x2 czy 5x5x4? pamięć jest liniowa wielowymiarowość tablic jest tylko interpretacją kompilatora! dlatego: void drukuj2(double tablica2[ ][10][2]); void drukuj2(double tablica2[ ][5][4]); to dwie różne funkcje podczas, gdy: void drukuj(double tablica[10]); void drukuj(double tablica[5]); są takie same i kompilator traktuje je tak: drukuj(double tablica[ ]);

Przykład: kopiowanie tablic znaków Tablica nie zna swojego rozmiaru void f(int pi[ ], int n, char pc[ ]) // ostrzeżenie: to nie jest bezpieczny kod, podajemy go jako przykład // nigdy nie zakładaj, że podany rozmiar jest poprawny { char buf1[200]; strcpy(buf1,pc); // kopiuje znaki z pc do buf1 // strcpy kończy działanie gdy napotka znak '\0' // zakładamy, że pc zawiera mniej niż 200 znaków strncpy(buf1,pc,200); // kopiuje 200 znaków z pc do buf1 // jeśli pc jest krótsze, wypełnia buf1 do końca znakami '\0' int buf2[300]; // nie można było utworzyć char buf2[n]; n jest zmienną if (300 < n) throw runtime_error("brak miejsca"); for (int i=0; i<n; ++i) buf2[i] = pi[i]; // zakładamy, że pi naprawdę zawiera // n int-ów. Mamy problem jeśli ma mniej... }

Adresy tablic a referencje Przekazywanie tablicy jako argumentu funkcji jest podobne do przekazywania argumentu przez referencję w obu przypadkach funkcja może modyfikować argument int modyfikuj_liczbe (int& a); int modyfikuj_tablice (int tab[]); Czy nazwa tablicy jest referencją? NIE referencja jest inną nazwą obiektu znajdującego się pod tym samym adresem, np. człowiek jan_kowalski; człowiek& mój_sąsiad = jan_kowalski nazwa tablicy jest niemodyfikowalnym oznaczeniem adresu pamięci

Odkryliśmy nowy byt: wskaźnik (ang. pointer) Wskaźnik jest adresem pamięci nazwa tablicy jest specjalnym przypadkiem wskaźnika Wskaźnik definiujemy następująco: typ_obiektu* nazwa_wskaźnika; wskaźnik wskazuje na obiekt określonego typu, np. double* liczba może wskazywać na liczbę double, a nie na string dzięki temu wiemy jak korzystać ze wskazywanego obiektu, np. to na co wskazuje double* można dodawać, a nie konkatenować

Adresy: operator & int a; char ac[20]; void f(int n) { int b; int* p = &b; p = &a; } pc: p: a: ac: // wskaźnik na pojedynczą zmienną lokalną // wskaźnik na pojedynczą zmienną globalną char* pc = ac; // wskaźnik na pierwszy element tablicy // możemy tak napisać, bo nazwa tablicy // jest rodzajem wskaźnika, ustawionym 1-szy element pc = &ac[0]; // równoważne pc = ac pc = &ac[n]; // wskaźnik na n-ty element tablicy (numerując od 0) // uwaga! zakres nie jest sprawdzany //

Dereferencja czyli wyłuskanie: operator * int a; char ac[20]; void f(int n) { int b; int* p = &b; char* pc = ac; } // wskaźnik na pojedynczą zmienną lokalną // wskaźnik na pierwszy element tablicy int b2 = *p; // wyłuskanie wartości typu int spod adresu p char c = *ac; // wyłuskanie wartości typu char spod adresu ac // (jest to pierwszy element tablicy ac) // to samo co: char c = ac[0]; c = *(ac+n); // wyłuskanie wartości n-tego elementu tablicy ac // to samo co: c = ac[n]; //

Wskaźniki Wskaźniki są adresami pamięci można je traktować jak pewne wartości całkowite pierwszy bajt pamięci ma adres 0, kolejny 1 itd. 0 1 2 p2 *p2 2^20-1 7 Wartości wskaźników można wyświetlić (ale rzadko się to przydaje) char c1 = 'c'; char* p1 = &c1; int i1 = 7; int* p2 = &i1; cout << "p1==" << p1 << " *p1==" << *p1 << "\n"; // p1==??? *p1==c cout << "p2==" << p2 << " *p2==" << *p2 << "\n"; // p2==??? *p2=7

źródło: http://en.wikipedia.org/wiki/pointer_%28dog_breed%29 Wskaźnik, czyli ang. pointer

Wskaźnik a referencja Referencja to automatycznie wyłuskiwany niemodyfikowalny wskaźnik, mówiąc prościej: przezwisko obiektu podstawienie do wskaźnika zmienia jego wartość podstawienie do referencji zmienia obiekt, do którego się odnosi nie można przestawić referencji na inny obiekt int a = 10; int* p = &a; // potrzebujesz & aby otrzymać adres zmiennej (wskaźnik na nią) *p = 7; // przypisanie wartości 7 do zmiennej a poprzez wskaźnik p // potrzebujesz * (lub [ ]) aby dostać się do tego, na co wskazuje wskaźnik int x1 = *p; // inicjuje zmienną x1 wartością zmiennej a poprzez wskaźnik p int& r = a; r = 9; int x2 = r; // r jest synonimem a // przypisanie wartości 9 do zmiennej a poprzez referencję r // inicjuje zmienną x2 wartością zmiennej a poprzez referencję r p = &x1; r = &x1; // możesz przestawić wskaźnik tak by odnosił się do innego obiektu // błąd: nie możesz przestawić referencji by odnosiła się do innego obiektu

Tablice i wskaźniki void f(int pi[ ]) // równoważne void f(int* pi) { int a[ ] = { 1, 2, 3, 4 }; int b[ ] = a; // błąd: kopiowanie nie jest zdefiniowane dla tablic. b = pi; // błąd: kopiowanie nie jest zdefiniowane dla tablic. // Nazwa tablicy jest niemodyfikowalnym wskaźnikiem pi = a; // dobrze, ale to NIE kopiuje tablicy: // teraz pi wskazuje na 1-szy element a int* p = a; // p wskazuje na pierwszy element a int* q = pi; // q wskazuje na pierwszy element a } pi: najpierw potem a: p: q: 1 2 3 4

Ostrożnie z tablicami i wskaźnikami char* f() { char ch[20]; char* p = &ch[90]; // *p = 'a'; char* q; *q = 'b'; return &ch[10]; // odczytaliśmy adres spoza zarezerwowanej dla ch pamięci // nie wiemy więc co teraz nadpisujemy // zapomnieliśmy zainicjować // nie wiemy co teraz nadpisujemy // O-o!: przecież ch zniknie gdy wyjdziemy z funkcji // a my zostaniemy z niesławnym wiszącym wskaźnikiem } void g() { char* pp = f(); // *pp = 'c'; // nie wiemy więc co teraz nadpisujemy // bo ch z funkcji f już dawno nie ma } Stroustrup/Programming Apr'10 24

Arytmetyka wskaźników char* mychar; short *myshort; long *mylong; // mychar++; myshort++; mylong++; // typ char zajmuje 1 bajt // typ short zajmuje 2 bajty // typ long zajmuje 4 bajty // Przesuwamy się w pamięci o: // 1 bajt // 2 bajty // 4 bajty źródło: http://www.cplusplus.com/doc/tutorial/pointers/ Tak samo działa zwiększanie wskaźnika o dowolną liczbę pozycji, np. mylong+=4 przesunie wskaźnik o 16 bajtów. Nie ma niejawnych konwersji pomiędzy wskaźnikami na różne typy chociaż istnieją niejawne konwersje pomiędzy typami: mychar = myshort; mylong = myshort; *mychar = *myshort; *mylong = *myshort; // błąd! // błąd! // ok // ok

Arytmetyka wskaźników (2) Co będzie wynikiem działania następujących poleceń? Zasady: operator ++ ma wyższy priorytet niż * preinkrementacja ++x zwiększa x przed użyciem postinkrementacja x++ zwiększa x po użyciu int *p; // cout << *p++ ; cout << *++p ; cout << (*p)++; cout << ++*p; // wyłuskaj obiekt, zwiększ wskaźnik, wyświetl obiekt // zwiększ wskaźnik, wyłuskaj obiekt, wyświetl obiekt // wyłuskaj obiekt, wyświetl obiekt, zwiększ obiekt, // wyłuskaj obiekt, zwiększ obiekt, wyświetl obiekt

Tworzenie tablic o rozmiarze określanym w czasie wykonania Często w trakcie pisania programu nie wiemy ile dokładnie pamięci zarezerwować na tablicę Taką tablicę możemy umieścić w pamięci wolnej void funkcja() { int wymiar_n, wymiar_m; cout << ''Podaj wymiary macierzy 2D: ''; cin >> wymiar_n, wymiar_m; int *macierz = new int[wymiar_n][wymiar_m]; // Do tworzenia obiektów // w pamięci wolnej służy służy operator new, // który zawsze zwraca wskaźnik for (n=0;n<wymiar_n;n++) for (m=0;m<wymiar_m;m++) { macierz[n][m]=(n+1)*(m+1); } } delete[ ] macierz; // Po zakończeniu pracy z tablicą w pamięci wolnej // należy ją usunąć operatorem delete[] // W przeciwnym przypadku mamy wyciek pamięci`

Tworzenie dowolnych obiektów w pamięci dynamicznej Alokuj używając new new alokuje obiekt w pamięci wolnej, czasami inicjuje go i zwraca wskaźnik do niego: int* pi = new int; // inicjacja domyślna (nieokreślona dla int) Date* pd = new Date(2012, Date::jan, 11); // inicjacja jawna używamy konstruktor double* pd = new double[10]; // alokacja tablicy (niezainicjowanej ) new rzuca wyjątek bad_alloc() jeśli nie uda się utworzyć obiektu De-alokuj używając delete i delete[ ] delete (dla pojedynczych obiektów) i delete[ ] (dla tablic) zwalnia pamięć zaalokowaną przez new delete pi; // dealokuje pojedyńczy obiekt delete pd; // dealokuje pojedyńczy obiekt, wywołuje destruktor obiektu delete[ ] pd; // dealokuje tablicę, wywołuje destruktor dla każdego elementu tablicy De-alokacja wskaźnika o adresie 0 (czyli null) niczego nie robi char* p = 0; delete p; // nieszkodliwe

Pamięć komputera tak jak widzi ją program: Statyczna alokacja pamięci Kod programu zmienne statyczne, zmienne globalne Pamięć statyczna nienazwane obiekty alokowane dynamicznie Dynamiczna alokacja pamięci Pamięć wolna (sterta, ang. heap) Stos (ang. stack) zmienne automatyczne tzn. zadeklarowane lokalnie, parametry funkcji

Gdzie żyją obiekty int glob[10]; int* some_fct(int n) { int loc[20]; int* wsk = new int[n]; // return wsk; } // tablica globalna żyje zawsze // tablica lokalna żyje do końca zakresu // tablica na stercie żyje aż nie usunięta przez delete[ ] void f() { int* pp = some_fct(17); // delete[ ] pp; // dealokacja tablicy w wolnej pamięci, zaalokowanej przez some_fct() } łatwo zapomnieć usunąć obiekt/tablicę zaalokowaną w pamięci wolnej unikaj new / delete (lub delete[ ]) jeśli możesz

Wektor jest sprytną tablicą Vector jest typem danych zdefiniowanym w bibliotece standardowej C++ vector<t> przechowuje sekwencję wartości typu T w zasadzie można powiedzieć, że wektor jest sprytną tablicą zna size() swój rozmiar i może go zmieniać, współpracuje z algorytmami biblioteki standardowej v: 5 elementy v: v[0] v[1] v[2] 1 4 2 v[3] 3 v[4] 5

vector czy tablica? vector<double> v_liczby; vector<string> v_slowa; vector<reading> v_odczyty; const int rozmiar = 10; double t_liczby[rozmiar]; string t_slowa[rozmiar]; Reading t_odczyty[rozmiar]; const int rozmiar = 10; vector<double> v_liczby2(rozmiar); for (int i=0; i<v_liczby2.size(); ++i) v_liczby2[i] = i*i; for (int i=0; i<rozmiar; ++i) t_liczby[i] = i*i; for (int i=0; i<v_liczby2.size(); ++i) cout << v_liczby2[i] << endl; for (int i=0; i<rozmiar; ++i) cout << t_liczby[i] << endl; Różnica: wektor zna swój rozmiar rozmiar tablicy musimy zapamiętać

vector czy tablica? #include <iostream> #include <string> #include <vector> #include <algorithm> using namespace std; #include <iostream> #include <string> #include <cmath> #include <cstring> using namespace std; while (cin>>s && s!= "quit") words.push_back(s); const int rozmiar=10; string words[rozmiar]; string s; int i=0; while (i<rozmiar && cin>>s && s!= "quit") words[i++] = s; sort(words.begin(), words.end()); qsort(words, rozmiar, sizeof(string), compare); for (int i=0; i<words.size(); ++i) cout<<words[i]<< "\n"; for (i=0; i<rozmiar; ++i) cout<<words[i]<< "\n"; vector<string> words; string s; Różnica: wektor współpracuje z wygodnymi algorytmami biblioteki standardowej int compare (const void * a, const void * b) { return strcmp(((string*)a)->c_str(),((string*)b)->c_str()); } Tablica - nie

Po co zajmować się tablicami? W języku C są tylko tablice w C nie ma wektorów istnieje bardzo dużo kodu w C systemy operacyjne, systemy wbudowane bardzo dużo kodu C++ zostało napisane w stylu C programując w C++ na pewno się z nim spotkasz Tablica jest najprostszą reprezentacją pamięci musisz więc co-nieco o nich wiedzieć ktoś kto napisał kontener vector wykorzystał tablicę Zasada: unikaj tablic, gdy tylko możesz są najczęstszym źródłem błędów w C i C++ są wśród najczęstszych źródeł luk bezpieczeństwa

vector czy tablica? Tam, blisko sprzętu, życie jest proste i brutalne musisz zaprogramować wszystko sam nie pomoże Ci kontrola typów błędy w czasie działania poznaje się po tym, że dane uległy uszkodzeniu lub program się wysypał O nie, chcemy się wyrwać stamtąd tak szybko jak się da chcemy być produktywni i pisać niezawodne programy chcemy używać języka odpowiedniego dla ludzi Dlatego używamy wektorów itp. ale chcemy też poznać techniki tworzenia nowych klas służących do pracy ze strukturami danych

Wskaźniki, tablice i vector Uwaga Używając wskaźników i tablic dotykasz sprzętu przy minimalnym wsparciu języka Stąd przy korzystaniu z nich łatwo o poważny i trudny do znalezienia błąd Należy z nich korzystać tylko wtedy kiedy naprawdę są potrzebne vector jest jednym ze rozwiązań by zachowując prawie całą elastyczność i wydajność tablic skorzystać z większego wsparcia języka (czytaj: mniej błędów, szybsze odrobaczanie)

Dziś najważniejsze było to, że... Tablice i wskaźniki są najprostszą reprezentacją pamięci w C/C++ są bardzo efektywne ale i bardzo błędogenne należy ich unikać gdy to tylko możliwe dobrym zastępstwem dla tablicy jest vector Pozostało jeszcze tyle do nauczenia, np. korzystanie z pamięci wolnej tworzenie typów użytkownika korzystających z pamięci wolnej programowanie zorientowane obiektowo (np. dziedziczenie) programowanie uogólnione (szablony, kontenery, iteratory)

A w przyszłym semestrze Dalsze spotkania z programowaniem na kursie Informatyka język wysokiego poziomu w środowisku Matlab rozwiązywanie problemów numerycznych graficzny interfejs użytkownika programowanie zorientowane obiektowo Ale zanim to nastąpi: kolokwium zaliczeniowe: pon., 16.01.2012, godz.19-21, sala 1.30/C-13 kolokwium poprawkowe: śr. 25.01.2012, godz. 13-15 (w sesji), sala 1.30/C-13

vector<double> v = { 1, 2, 3.456, 99.99 }; template<class E> class vector { public: vector (std::initializer_list<e> s) // initializer-list constructor { reserve(s.size()); // get the right amount of space uninitialized_copy(s.begin(), s.end(), elem); // initialize elements (in elem[0:s.size())) sz = s.size(); // set vector size } Listy inicjacyjne C++11 //... as before }; vector<double> v1(7); v1 = 9; vector<double> v2 = 9; vector<double> v1{7}; v1 = {9}; vector<double> v2 = {9}; // ok: v1 has 7 elements // error: no conversion from int to vector // error: no conversion from int to vector // ok: v1 has 1 element (with its value 7) // ok v1 now has 1 element (with its value 9) // ok: v2 has 1 element (with its value 9) int x0 {7.3}; // error: narrowing int x1 = {7.3}; // error: narrowing; the = is optional double d = 7; int x2{d}; char x3{7}; vector<int> vi = { 1, 2.3, 4, 5.6 }; // error: narrowing (double to int) // ok: even though 7 is an int, this is not narrowing // error: double to int narrowing http://www2.research.att.com/~bs/c++0xfaq.html#init-list