Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] Dynamiczna alokacja pamięci - jakie jest jej zastosowanie?

Ostatnio zmodyfikowano 2013-09-25 00:26
Autor Wiadomość
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.

C/C++
#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:

C/C++
#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:)
P-92576
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.
P-92582
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...?
P-92634
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).
P-92635
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
P-92642
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:
C/C++
#include <cstdio>
int main()
{
    int iRozmiar = 0;
    int t[ iRozmiar ]; //Tablica nie posiada przydzielonej pamięci, ale wskazuje na jakiś adres w pamięci
    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; //piszemy po pamięci
        printf( "Adres 't[%d]': 0x%p; wartosc 'zmienna' = %d\n", i, & t[ i ], zmienna );
        if( zmienna != 0 )
             printf( "Wartosc zmiennej ulegla nadpisaniu!\n" );
       
    } //for
   
    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
P-92644
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.
P-92645
« 1 »
  Strona 1 z 1