Frish Temat założony przez niniejszego użytkownika |
[C++] Dynamiczna alokacja pamięci - jakie jest jej zastosowanie? » 2013-09-24 12:33:16 witam chciałbym się zapytać o jedną rzecz, bo niestety nie potrafie do konca zrozumiec o co chodzi z ta dynamiczna alokacja pamieci, jaki praktyczny sens ona posiada. tutaj jest ten kod z alokacja. #include <iostream>
int main() { int rozmiar_tablicy; int wartosc; std::cout << "Podaj wartosc: "; std::cin >> rozmiar_tablicy; std::cout << std::endl << "stworzono tablice zlozonej z " << rozmiar_tablicy << " elementow" << std::endl; int * liczba = new int[ rozmiar_tablicy ]; for( int i = 0; i < rozmiar_tablicy; i++ ) { std::cout << "Podaj wartosc " << i << " elementu: "; std::cin >> wartosc; liczba[ i ] = wartosc; } for( int i = 0; i < rozmiar_tablicy; i++ ) { std::cout << std::endl << "element nr " << i << ": " << liczba[ i ]; } delete[] liczba; return 0; }
a ja napisalem coś podobnie działającego i teraz nie wiem jaka jest różnica miedzy tymi programami? czyli gdzie tkwi praktyczna różnica w wykorzystaniu tej dynamicznej alokacji danych? oto co napisałem: #include <iostream>
int main() { int i = 0; int rozmiar_tablicy; int liczba[ i ]; int wartosc; std::cout << "Podaj wartosc: "; std::cin >> rozmiar_tablicy; std::cout << std::endl << "stworzono tablice zlozona z " << rozmiar_tablicy << " elementow" << std::endl; for( i = 0; i < rozmiar_tablicy; i++ ) { std::cout << std::endl << "Podaj wartosc: " << i << " elementu"; std::cin >> wartosc; liczba[ i ] = wartosc; } for( int i = 0; i < rozmiar_tablicy; i++ ) { std::cout << std::endl << "element nr " << i << ": " << liczba[ i ]; } std::cin >> i; std::cout << std::endl << "element nr: " << liczba[ i ]; return 0; }
proszę o odpowiedz:) |
|
SeaMonster131 |
» 2013-09-24 13:12:40 Kompilator powinien wyrzucić Ci warning/error, w przypadku gdzie wielkość tablicy nie jest znana podczas kompilacji. Dodatkowo wydaje mi się, że w tym 2. kodzie masz wyciek pamięci, gdyż teoretycznie tablica liczba[] nie ma żadnych elementów, a Ty nadajesz im jakieś wartości. |
|
Frish Temat założony przez niniejszego użytkownika |
» 2013-09-24 20:33:08 jezeli chodzi o blad to nie wyrzuca mi go poniewaz nadalem wartosc poczatkowa "0" tablicy i pozniej w petli jest tworzona dalej tablica ale z tym drugim sie zgodze jest wyciek pamieci...i teraz chce sie dowiedziec czy tylko w tym jest przewaga stosowania alokacji pamieci i czy tylko o minimalizacje zurzycia pamieci chodziw tej alokacji...?...czy moze sa jeszcze jakies dodatkowe atuty tego sposobu ktore wynikaja dodatkowo z jego uzywania i jezeli takie sa to w czym one sie przejawiaja, do czego jeszcze ta alokacja jest przydatna w jakich konkretnych sytuacjach procz oczywistego wycieku pamieci...? |
|
DejaVu |
» 2013-09-24 21:12:05 Jezeli chodzi o blad to nie wyrzuca mi go poniewaz nadalem wartosc poczatkowa "0" tablicy i pozniej w petli jest tworzona dalej tablica ale z tym drugim sie zgodze jest wyciek pamieci...i teraz chce sie dowiedziec czy tylko w tym jest przewaga stosowania alokacji pamieci i czy tylko o minimalizacje zurzycia pamieci chodziw tej alokacji...?.
|
Nadając rozmiar tablicy 0, piszesz poza zakresem tablicy w chwili próby przypisania jakiejkolwiek wartości do któregokolwiek elementu tablicy. Aplikacja zachowa się więc w sposób niezdefiniowany (zazwyczaj aplikacja się wysypuje). /edit: Odpowiadając na pytanie postawione w temacie - alokując pamięć dynamicznie możesz decydować kiedy ją zwolnisz tj. kiedy uznasz, że dane w niej zapisane są niepotrzebne. Alokując pamięć na stosie (czyli tworząc zwykłą zmienną/tablicę) wiesz, że ta zmienna przestanie istnieć (a razem z nią dane) po wyjściu z zasięgu zmiennej. Dzięki dynamicznej alokacji pamięci możesz napisać osobną funkcję, która utworzy tablicę o zadanym rozmiarze, osobną funkcję, która wczyta dane do takiej tablicy i osobną funkcję, która będzie tą tablicę usuwała, zapisując przy okazji dane na dysk przed ich usunięciem. W przypadku tworzenia lokalnej zmiennej nie jesteś w stanie utworzyć tablicy w funkcji, tylko funkcja musi pracować na tablicy przekazanej poprzez argument - w przeciwnym wypadku dane będą ulegały utracie i w zasadzie aplikacja będzie niesprawna. Stos jest ograniczony do 1MB - można modyfikować opcjami linkera (stos = pamięć przeznaczona na zmienne tymczasowe i wykorzystywania do wywołań wszelkich funkcji i metod). Sterta jest ograniczona do 2GB dla procesu 32-bitowego (sterta = dynamiczna alokacja pamięci). |
|
Frish Temat założony przez niniejszego użytkownika |
» 2013-09-24 23:35:44 właśnie o takie wyjaśnienie mi chodziło...
chodzi mi tylko jeszcze o tą kwestię z tą tablica...nadałem tablicy wartość zero ale dopiero w pętli dałem jej wyższe wartości czy to nadal jest pisanie poza tablica...odpowiedz mi na podstawie tego kodu który tu wstawiłem, chodzi o drugi kod...i jeżeli chodzi o to wywalenie z programu to właśnie z tym się nic nie dzieje, nie wysypuje go...ten program jest błędnie napisany?
pozdrawiam |
|
DejaVu |
» 2013-09-25 00:11:14 Przetestuj swój program dla większych zestawów danych, np. dla 20 liczb. Skoro tablica ma 0 elementów to znaczy, że nie przeznaczono dla niej pamięci. Zmienna mimo wszystko wskazuje na jakiś adres w pamięci, ale nie jest 'właścicielem' tych danych. Przykład: #include <cstdio> int main() { int iRozmiar = 0; int t[ iRozmiar ]; int zmienna = 0; printf( "Adres 'iRozmiar': 0x%p\n", & iRozmiar ); printf( "Adres 't[0]': 0x%p\n", & t[ 0 ] ); printf( "Adres 'zmienna': 0x%p\n", & zmienna ); for( int i = 0; i < 100; i++ ) { t[ i ] = 999; printf( "Adres 't[%d]': 0x%p; wartosc 'zmienna' = %d\n", i, & t[ i ], zmienna ); if( zmienna != 0 ) printf( "Wartosc zmiennej ulegla nadpisaniu!\n" ); } return 0; }
Możliwe dane na standardowym wyjściu programu: Adres 'iRozmiar': 0x0028ff00 Adres 't[0]': 0x0028fed0 Adres 'zmienna': 0x0028fefc Adres 't[0]': 0x0028fed0; wartosc 'zmienna' = 0 Adres 't[1]': 0x0028fed4; wartosc 'zmienna' = 0 Adres 't[2]': 0x0028fed8; wartosc 'zmienna' = 0 Adres 't[3]': 0x0028fedc; wartosc 'zmienna' = 0 Adres 't[4]': 0x0028fee0; wartosc 'zmienna' = 0 Adres 't[5]': 0x0028fee4; wartosc 'zmienna' = 0 Adres 't[6]': 0x0028fee8; wartosc 'zmienna' = 0 Adres 't[7]': 0x0028feec; wartosc 'zmienna' = 0 Adres 't[8]': 0x0028fef0; wartosc 'zmienna' = 0 Adres 't[9]': 0x0028fef4; wartosc 'zmienna' = 0 Adres 't[10]': 0x0028fef8; wartosc 'zmienna' = 0 Adres 't[11]': 0x0028fefc; wartosc 'zmienna' = 999 Wartosc zmiennej ulegla nadpisaniu! Adres 't[12]': 0x0028ff00; wartosc 'zmienna' = 999 Wartosc zmiennej ulegla nadpisaniu! Adres 't[13]': 0x0000041b; wartosc 'zmienna' = 999 Wartosc zmiennej ulegla nadpisaniu! /* (...) i tu aplikacja się wysypuje */
Dodam jeszcze, że Visual C++ 2012 nie przepuści Ci powyższego kodu i rzuci błędem kompilacji: error C2057: expected constant expression error C2466: cannot allocate an array of constant size 0 error C2133: 't' : unknown size
|
|
Frish Temat założony przez niniejszego użytkownika |
» 2013-09-25 00:26:30 czyli rozumiem że jak tablice to tylko w połączeniu z dynamiczną alokacją danych...?:)
jeszcze raz dzięki za poświęcony czas i tak precyzyjne objaśnienie tematu. Teraz mam rozjaśnione spojrzenie na kwestię tego tematu i dostrzegłem jak ważna jest dynamiczna alokacja przy pisaniu programów. |
|
« 1 » |