logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[C++] Tworzenie tablicy dynamicznej dwuwymiarowej

malum 06 Lis 2009 00:01 31322 28
REKLAMA
  • #1 7221669
    malum
    Poziom 23  
    Posty: 883
    Pomógł: 1
    Ocena: 141
    Witam!
    Zastanawiam się nad sposobem tworzenia tablicy dynamicznej w C++
    Zgodnie z wszelkimi opisami jakie znalazłem, tablicę dwuwymiarową tworzymy tak:

    
      int w=10, k=10;
      int **tab = new int *[w];
      for ( int i = 0; i < w; ++i )
         tab[i] = new int [k];
    


    co jednak stoi na przeszkodzie, żeby tablicę taką deklarować tak:

    
    int w=10, k=10;
    int tab[w][k];  
    


    Obie wersje działają teoretycznie tak samo, natomiast druga wersja jest nieporównywalnie prostsza i bardziej naturalna.
  • REKLAMA
  • #2 7222688
    marihires
    Poziom 30  
    Posty: 986
    Pomógł: 193
    Ocena: 130
    Ten drugi kod nie przedstawia tablicy dynamicznej.
    Teoretycznie nie działają tak samo :).
    Pozdrawiam.
  • REKLAMA
  • #3 7222775
    jestam
    Specjalista Automatyk
    Posty: 1799
    Pomógł: 210
    Ocena: 145
    int ** tab to nie jest tablica dwuwymiarowa. Jest to jednowymiarowa tablica wskaźników, wskazujących jednowymiarowe tablice int.

    alokujesz tablicę wskaźników do int liczącą w elementów:
    int **tab = new int *[w];

    następnie w pętli alokujesz w tablic int po k elementów każda i przypisujesz ich adresy elementom tablicy tab:

    for ( int i = 0; i < w; ++i ) tab[i] = new int [k];

    Nie ma nawet wymogu, żeby wszystkie tablice int miały ten sam rozmiar, np. można napisać

    for ( int i = 0; i < w; ++i ) tab[i] = new int [k * (i+1)];
  • #4 7222923
    Dr.Vee
    VIP Zasłużony dla elektroda
    Posty: 1784
    Pomógł: 307
    Ocena: 76
    malum napisał:
    co jednak stoi na przeszkodzie, żeby tablicę taką deklarować tak:

    
    int w=10, k=10;
    int tab[w][k];  
    


    Tablica byłaby dynamiczna, gdyby dało się ją zadeklarować np. tak:
    
    extern unsigned w;
    extern unsigned h;
    
    int tab[w][h];


    Może najpierw próbuj kompilować kod, który wysyłasz na forum? :)

    Pozdrawiam,
    Dr.Vee
  • #5 7222975
    malum
    Poziom 23  
    Posty: 883
    Pomógł: 1
    Ocena: 141
    Dr.Vee napisał:
    Może najpierw próbuj kompilować kod, który wysyłasz na forum? :)
    Pozdrawiam,
    Dr.Vee


    Oj, chyba drogi moderator czegoś nie doczytał...
    Proszę więc bardzo, kod przykładowego programu:

    
    #include<iostream>
    using namespace std;
    
    int main()
    {
      int a,b,lp=0;
      cout << "Podaj ilosc wierszy tablicy : ";
      cin >> a;
      cout << "Podaj ilosc kolumn tablicy : ";
      cin >> b; 
      cout << endl;
      
      int tab[a][b];
      
      // wczytywanie danych do tablicy
      for(int i=0;i<a;i++)
        for(int j=0;j<b;j++)
        {
          tab[i][j] = lp;
          lp++; 
        } 
        
      // odczytch danych z tablicy
      for(int i=0;i<a;i++)
        for(int j=0;j<b;j++)
        {
          cout << tab[i][j] << " "; 
        }   
      cout << endl << endl;
      system("pause");
      return 0;  
    }
    


    a poniżej wersja cpp i exe
    Załączniki:
    • tablica.exe (572.06 KB) Musisz być zalogowany, aby pobrać ten załącznik.
    • tablica.cpp (575 Bajtów) Musisz być zalogowany, aby pobrać ten załącznik.
  • #6 7223281
    Dr.Vee
    VIP Zasłużony dla elektroda
    Posty: 1784
    Pomógł: 307
    Ocena: 76
    Twój kompilator może takie rzeczy opcjonalnie wspierać (mój też wspiera), ale nie zmienia to faktu że ISO C++ nie zezwala na takie zachowanie:
    g++ -Wall -pedantic    tablica.cpp   -o tablica
    tablica.cpp: In function `int main()':
    tablica.cpp:13: error: ISO C++ forbids variable-size array `tab'

    Tak samo dla zmiennych globalnych (przykład z extern) i dla atrybutów klasy...

    Tak czy inaczej najlepiej skorzystać z odpowiedniej abstrakcji, np. własnej klasy/wzorca albo stl::vector. Zwykłe tablice (zwłaszcza dynamiczne) generują zbyt dużo potencjalnych błędów.

    Pozdrawiam,
    Dr.Vee
  • #7 7224294
    malum
    Poziom 23  
    Posty: 883
    Pomógł: 1
    Ocena: 141
    Dr.Vee napisał:
    Twój kompilator może takie rzeczy opcjonalnie wspierać (mój też wspiera), ale nie zmienia to faktu że ISO C++ nie zezwala na takie zachowanie:
    g++ -Wall -pedantic    tablica.cpp   -o tablica
    tablica.cpp: In function `int main()':
    tablica.cpp:13: error: ISO C++ forbids variable-size array `tab'

    Tak samo dla zmiennych globalnych (przykład z extern) i dla atrybutów klasy...

    Tak czy inaczej najlepiej skorzystać z odpowiedniej abstrakcji, np. własnej klasy/wzorca albo stl::vector. Zwykłe tablice (zwłaszcza dynamiczne) generują zbyt dużo potencjalnych błędów.

    Pozdrawiam,
    Dr.Vee


    Mogę w związku z tym prosić o przykładowy program z tablicami dynamicznymi, bo gdy wpisuję "tablice dynamiczne c++" w google to jedyne co mi się pokazuje to wersja ze wskaźnikami, które w/g przedmówcy nie są tablicami, i ma on rację, ale w dalszym ciągu nie wiem jak zbudować poprawną tablicę dynamiczną jedno i dwuwymiarową :(
  • REKLAMA
  • #8 7224816
    several
    Poziom 15  
    Posty: 140
    Pomógł: 14
    Ocena: 1
    W drugim przypadku wartości zmiennych w i h będziesz musiał deklarować w programie, nie będziesz mógł ich wartości przypisać przez cin naprzykład.

    "Wersja ze wskaźnikami" polega na tym że najpierw alokujesz sobie odpowiednią ilość pamięci a dopiero później deklarujesz konkretny rozmiar tablicy. Robisz to wtedy gdy na etapie tworzenia kodu nie wiesz jaki rozmiar tablicy będziesz potrzebował lub ten rozmiar będzie się zmieniał.

    A jeśli chcesz przykładu to powiedzmy że chcesz wykonać jakieś operacje na grafice, jasne jest że nie chcesz się zastanawiać jaki rozmiar ma ta grafika i czy przypadkiem nie musisz zmieniać kodu by ją wczytać, chcesz żeby się wczytywała niezależnie od rozmiaru, wtedy tworzysz sobie tablicę dynamiczne wg sposobu pierwszego.
  • #9 7225064
    malum
    Poziom 23  
    Posty: 883
    Pomógł: 1
    Ocena: 141
    several napisał:
    W drugim przypadku wartości zmiennych w i h będziesz musiał deklarować w programie, nie będziesz mógł ich wartości przypisać przez cin naprzykład.

    "Wersja ze wskaźnikami" polega na tym że najpierw alokujesz sobie odpowiednią ilość pamięci a dopiero później deklarujesz konkretny rozmiar tablicy. Robisz to wtedy gdy na etapie tworzenia kodu nie wiesz jaki rozmiar tablicy będziesz potrzebował lub ten rozmiar będzie się zmieniał.

    A jeśli chcesz przykładu to powiedzmy że chcesz wykonać jakieś operacje na grafice, jasne jest że nie chcesz się zastanawiać jaki rozmiar ma ta grafika i czy przypadkiem nie musisz zmieniać kodu by ją wczytać, chcesz żeby się wczytywała niezależnie od rozmiaru, wtedy tworzysz sobie tablicę dynamiczne wg sposobu pierwszego.


    Mogę deklarować wielkość cin'em, przecież nawet powyżej zamieściłem działający program.
    Piszesz, że mam utworzyć tablicę dynamiczną w/g pierwszego przykładu, ale to nie jest tablica dynamiczna, tylko tablica wskaźników i działa dokładnie tak samo jak drugi przykład. Może formalnie to nie jest pięknie napisane, ale działa - DevC++ kompiluje ten kod bez zastrzeżeń!
    Co do przykłady, to wolałbym raczej coś na zasadzie kodu, a nie przykład teoretyczny, bo teoretycznie wiem co to jest zmienna dynamiczna, ale w praktyce nigdzie takiej znaleźć nie mogę. Jeśli masz jakiś kod to podeślij na forum, przyda się pewnie wielu elektrodowcom.
  • #10 7225184
    jestam
    Specjalista Automatyk
    Posty: 1799
    Pomógł: 210
    Ocena: 145
    Cytat:

    Mogę w związku z tym prosić o przykładowy program z tablicami dynamicznymi, bo gdy wpisuję "tablice dynamiczne c++" w google to jedyne co mi się pokazuje to wersja ze wskaźnikami, które w/g przedmówcy nie są tablicami, i ma on rację, ale w dalszym ciągu nie wiem jak zbudować poprawną tablicę dynamiczną jedno i dwuwymiarową


    Jednowymiarowa tablica dynamiczna: int * tab = new int[rozmiar];

    Tablice dwu- i więcej wymiarowe są dość specyficzne. Np. int tab2 [2][3] to 2 * 3 = 6 kolejnych liczb int. Jeżeli chcesz się odwołać do elementu tab2[i][j] to kompilator przelicza [i * 3 + j] i odwołuje się do tego właśnie elementu.

    Jak to zrealizować dynamicznie:
    
    int* tabDyn = new int [w * k];
    int lp = 0;
    for(int i=0;i<w;i++) 
    {
        for(int j=0;j<k;j++) 
        { 
             tabDyn[i * k + j] = lp; 
             lp++; 
        }
    }
    


    Ale zwróć uwagę, że dla tablicy wskaźników do tablic int (jak w 1. przykładzie):
    
      int **tabW = new int *[w]; 
      for ( int i = 0; i < w; ++i ) 
         tabW[i] = new int [k]; 
    

    zapis tabW[i][j] także jest poprawny i znaczy on zupełnie co innego niż tab2[i][j] !

    Dlatego
    Dr.Vee napisał:

    Tak czy inaczej najlepiej skorzystać z odpowiedniej abstrakcji, np. własnej klasy/wzorca albo stl::vector. Zwykłe tablice (zwłaszcza dynamiczne) generują zbyt dużo potencjalnych błędów.
  • #11 7225227
    malum
    Poziom 23  
    Posty: 883
    Pomógł: 1
    Ocena: 141
    jestam napisał:

    Jednowymiarowa tablica dynamiczna: int * tab = new int[rozmiar];


    Czy to nie jest utrudnianie sobie życa, skoro działa też klasyczna konstrukcja int tab[rozmiar]; gdzie [rozmiar] może być określony w dowolnym miejscu programu w zależności od potrzeb? Efekt działania jest dokładnie taki sam jak int * tab = new int[rozmiar]; tylko prostszy w zapisie. Może faktycznie jak wspomniał Dr.Vee może nie jest to zgodne z ISO C++, ale skoro działa i kompilatory sobie z tym radzą to może po prostu język się rozwija i "czas na zmiany..."

    Interesuje mnie jednak tylko jedno, i to jest jak dla mnie chyba jedyna różnica, albo czegoś nie wiem - jak zwolnić pamięć? Tablicę tworzoną za pomocą new usuwa się poleceniem delete, a co z drugim rodzajem tablicy? Czy da się jakoś zwolnić pamięć?
  • #13 7225429
    malum
    Poziom 23  
    Posty: 883
    Pomógł: 1
    Ocena: 141
    marihires napisał:
    Skieruję Cie do poczytania o tablicach statycznych i dynamicznych:

    Link1
    Link2
    Link3

    Jakie różnice po przeczytaniu tego widzisz w tych zapisach:

    int * tab = new int[rozmiar];


    int tab[rozmiar]


    :?:

    Pozdrawiam.


    Przeczytałem, ale nie bardzo rozumiem do czego zmierzasz.
    Wiem jak tworzyć tablice dynamiczne int * tab = new int[rozmiar]; bo sam tak robię od lat, ale zdziwiłem się, jak przypadkowo bawiąc się zmiennymi zastosowałem zapis int tab[rozmiar]; i program również zadziałał.
    Interesują mnie mocne argumenty przeciwko drugiej, krótszej wersji, która też działa. Jednym z argumentów może być zwalnianie pamięci, ale ... i stąd moje pytanie, czy da się jakoś zwolnić pamięć w prostszym przykładzie?
    Strony które mi podesłałeś niczego nowego nie wniosły.
  • #14 7227314
    several
    Poziom 15  
    Posty: 140
    Pomógł: 14
    Ocena: 1
    malum napisał:


    Mogę deklarować wielkość cin'em, przecież nawet powyżej zamieściłem działający program.[...]
    Może formalnie to nie jest pięknie napisane, ale działa - DevC++ kompiluje ten kod bez zastrzeżeń!


    Jeden kompilator to przyjmie a inny nie. Poniższy kod:
    
            int w, h;
    	cout<<"podaj w"<<endl;
    	cin>>w;
    	cout<<"podaj h"<<endl;
    	cin>>h;
    	int tab[h][w];
    


    nie jest dobry. VC++ 2k8 EE wyrzucił 6 błędów przy kompilacji.
  • #15 7227381
    malum
    Poziom 23  
    Posty: 883
    Pomógł: 1
    Ocena: 141
    several napisał:
    malum napisał:


    Mogę deklarować wielkość cin'em, przecież nawet powyżej zamieściłem działający program.[...]
    Może formalnie to nie jest pięknie napisane, ale działa - DevC++ kompiluje ten kod bez zastrzeżeń!


    Jeden kompilator to przyjmie a inny nie. Poniższy kod:
    
            int w, h;
    	cout<<"podaj w"<<endl;
    	cin>>w;
    	cout<<"podaj h"<<endl;
    	cin>>h;
    	int tab[h][w];
    


    nie jest dobry. VC++ 2k8 EE wyrzucił 6 błędów przy kompilacji.


    Wierzę i o tym samym było już mówione kilka razy, ale powtórzę...
    W DevC++ program kompilowany jest bez problemu. Zdaję sobie sprawę, że wiele kompilatorów sobie z tym nie poradzi, ale ... no i tu trzeba problem przemyśleć.
    Tak jak każdy człowiek powinien się rozwijać, tak i programy się rozwijają. Odnosząc się choćby do Pascala, to ostatnią wersją było Borland Pascal 7.0, czyli wcześniej było przynajmniej 6 wersji gorszych, ale przez ewolucję pascal jest tym czym jest. Podobnie z C++, też się rozwija. Może ten skrócony zapis nie jest wcale błędny tylko powstał dzięki ewolucji kompilatorów, a te które sobie z tym nie radzą może są po prostu za stare? Teoretycznie rzecz biorąc w C++ nie ma tablic dynamicznych, bo te które sa tak nazywane są w zasadzie wskaźnikami. Jedynie to co ja podałem można w pełni nazwać tablicą dynamiczną i może właśnie do niej powinny zostać dopasowane kompilatory. Przemyślcie to i nie zakładajcie z góry, że jak Wasz kompilator sobie z tym nie radzi to znaczy że to jest złe!
    Czy jak kupisz sobie komputer z napędem CD to powiesz, że używanie płyt DVD jest niezgodne z zasadami czy poszukasz nowego komputera z napędem DVD? Tak samo z przykładem tych tablic, nie zakładajmy, że skoro Wasz kompilator nie radzi sobie z taką tablicą to oznacza, że nie wolno takiej używać, tylko poszukajcie kompilatora, który jest bardziej rozbudowany od waszego, podobnie jak z CD i DVD - czy nie mam racji?
  • #16 7227457
    several
    Poziom 15  
    Posty: 140
    Pomógł: 14
    Ocena: 1
    malum napisał:

    W DevC++ program kompilowany jest bez problemu. Zdaję sobie sprawę, że wiele kompilatorów sobie z tym nie poradzi


    IMHO to nie jest kwestia czy kompilator sobie poradzi czy nie, tylko czy taki zapis jest poprawny. Dev od wieków nie był aktualizowany, żaden aktualny kompilator nie powinien przyjąć tego zapisu. Jeżeli na etapie tworzenia kodu nie wiesz jakiego rozmiaru tablicy będziesz potrzebował implementujesz tablice dynamiczne, jeżeli wiesz dokładnie jaka tablica ma mieć rozmiar używasz tablic o rozmiarze stałym. Wg mnie nie ma co roztrząsać za bardzo tej kwestii.
  • REKLAMA
  • #17 7227506
    malum
    Poziom 23  
    Posty: 883
    Pomógł: 1
    Ocena: 141
    several napisał:
    malum napisał:

    W DevC++ program kompilowany jest bez problemu. Zdaję sobie sprawę, że wiele kompilatorów sobie z tym nie poradzi


    IMHO to nie jest kwestia czy kompilator sobie poradzi czy nie, tylko czy taki zapis jest poprawny. Dev od wieków nie był aktualizowany, żaden aktualny kompilator nie powinien przyjąć tego zapisu. Jeżeli na etapie tworzenia kodu nie wiesz jakiego rozmiaru tablicy będziesz potrzebował implementujesz tablice dynamiczne, jeżeli wiesz dokładnie jaka tablica ma mieć rozmiar używasz tablic o rozmiarze stałym. Wg mnie nie ma co roztrząsać za bardzo tej kwestii.


    Ale dlaczego?
    Dlaczego nie można określać rozmiaru tablicy po uruchomieniu programu? Podaj logiczne argumenty. Masz rację, że DevC++ nie był aktualizowany, ale kompiluje, a te aktualizowane nie... Może bronią się jak mogą przed tego rodzaju zabiegami. Producenci niemieckich samochodów do niedawna wypierali się stosowania w dislach wtrysku bezpośredniego, a teraz stosują, Nikon zapierał sie, że nigdy nie zrobi lustrzanki z pełnowymiarową matrycą, a robi, może czas na programistów... Po co sobie zycie utrudniać?
  • #18 7227943
    several
    Poziom 15  
    Posty: 140
    Pomógł: 14
    Ocena: 1
    malum napisał:

    Dlaczego nie można określać rozmiaru tablicy po uruchomieniu programu?

    Ależ można! Tylko wtedy w kodzie trzeba zaimplementować tablicę dynamiczną ;)
  • #19 7232439
    malum
    Poziom 23  
    Posty: 883
    Pomógł: 1
    Ocena: 141
    several napisał:
    malum napisał:

    Dlaczego nie można określać rozmiaru tablicy po uruchomieniu programu?

    Ależ można! Tylko wtedy w kodzie trzeba zaimplementować tablicę dynamiczną ;)


    W moim przykładzie z DevC++ też można, więc wszystko gra :-)
  • #20 7232924
    jestam
    Specjalista Automatyk
    Posty: 1799
    Pomógł: 210
    Ocena: 145
    malum napisał:

    Może bronią się jak mogą przed tego rodzaju zabiegami


    Nie szukaj spisków ;)

    Użyj debuggera i zobacz jaki kod jest generowany dla int tab[h][w];
    Porównaj z kodem generowanym dla int tab[2][3] oraz new int[2*3] i wyciągnij wnioski.
  • #21 7234283
    Dr.Vee
    VIP Zasłużony dla elektroda
    Posty: 1784
    Pomógł: 307
    Ocena: 76
    Kod przytoczony przez kolegę malum się kompiluje, bo DevC++ "pod maską" używa MinGW, czyli GCC. GCC wspiera standard ISO C99, który dopuszcza takie deklaracje (nazywa się to VLA = Variable Length Array). Ponieważ kompilator C++ w GCC (czyli g++) korzysta z tego samego generatora kodu, to VLA są w nim wspierane również w C++, choć de facto nie są częścią standardu.

    Akurat w GCC VLA są alokowane na stosie (choć nie jest to wymaganie VLA). Jest to znacząca różnica, gdyż pamięć dla tablic alokowanych przez new domyślnie pochodzi ze sterty.

    Pozdrawiam,
    Dr.Vee
  • #22 7235093
    malum
    Poziom 23  
    Posty: 883
    Pomógł: 1
    Ocena: 141
    jestam napisał:

    Nie szukaj spisków ;)


    Nie szukam :-)
    Zastanawiam się jedynie nad definicją tablicy dynamicznej i próbuję ją przenieść do C++. Do tej pory nie czuję się przekonany, że konstrukcja
     int * tab = new int[rozmiar];
    to tablica dynamiczna, zresztą sami mnie na samym początku poprawiliście, że to nie tablica a wskaźniki. Prawdziwa tablica dynamiczna to zwykła tablica, a której można zadeklarować rozmiar w czasie działania programu, czyli
     int tab[rozmiar] 
    Skoro DevC++ taką konstrukcję kompiluje, działa ona w 100% poprawnie, jest znacznie łatwiejsza w użyciu, zwłaszcza przy stosowaniu tablic wielowymiarowych to dlaczego jej nie używać? Może problemem nie jest DevC++ czy inny kompilator, a po prostu niechęć programistów do zmian? Gdy 70 latkowi pokażecie komputer to się skrzywi, ale gdy się nauczy to odejść nie chce. W/g mnie wszyscy producenci oprogramowania powinni przejść na taki sposób deklarowania tablic dynamicznych, jest łatwiejszy, szybszy i bardziej intuicyjny. Nie trzeba wertować kilkudziesięciu stron czy książek, żeby utworzyć tablicę dynamiczną, wystarczy wiedzieć jak wygląda zwykła tablica. Co więcej, dysponując taką konstrukcją tablicy dynamicznej możemy "zaprzestać" używania standardowych tablic, bo i po co, skoro można zadeklarować jej wielkość tuż przed użyciem. Chciałbym właśnie dowiedzieć się od was jakie są wady takiego rozwiązania, ale konkretnie, np. o20% większe zużycie pamięci, o 40% zmniejszona wydajność programu itd. bo to byłyby faktycznie argumenty przeciw, ale skoro ich nie ma...
  • #23 7235465
    several
    Poziom 15  
    Posty: 140
    Pomógł: 14
    Ocena: 1
    malum napisał:
    Skoro DevC++ taką konstrukcję kompiluje[...]

    Kompiluje bo jest stary i nieaktualizowany. Jeżeli swoje argumenty opierasz tylko na tym "bo DevC++ to kompiluje" to Twoja argumentacja jest bardzo biedna. Jeżeli chcesz tak pisać to pisz, wiedz jednak że zdecydowana większość IDE takiej składni Ci nie przyjmie, a napewno żaden na bieżąco aktualizowany i rozwijany. W momencie gdy C++ stanie się dla Ciebie narzędziem a nie celem to przyznasz mi rację ;)
    malum napisał:

    Może problemem nie jest DevC++ czy inny kompilator, a po prostu niechęć programistów do zmian?

    O rany człowieku, popłynąłeś po krawędzi, prawie z krzesła spadłem :D Ale powiem Ci, że częściowo masz rację, z tym że jedynym "programistą" który ma jakąś niechęć do zmian jesteś Ty ;) Przeczytaj jeszcze raz posty kolegów mądrzejszych od siebie(ode mnie zresztą też) zanim coś jeszcze napiszesz.
  • #24 7235492
    jestam
    Specjalista Automatyk
    Posty: 1799
    Pomógł: 210
    Ocena: 145
    
    int * tab = new int[rozmiar];
    

    jest dynamiczną, jednowymiarową tablicą int. W języku C/C++ nazwa tablicy jest wskaźnikiem jej pierwszego elementu, a nawiasy [] można użyć z dowolnym wskaźnikiem:
    
    int tab[10];
    int * wsk = tab;
    wsk[2] = 5;
    


    Pewien kłopot powstaje dla dynamicznych tablic wielowymiarowych, które można utworzyć jako tablicę wskaźników (do tablic wskaźników) do tablic jednowymiarowych i używać składni tab_dyn[i][j] lub utworzyć je jako ciągły obszar pamięci o długości tab_dyn[i*j] i odwoływać się do komórek przez tab_dyn[i*liczba_kolumn + j].

    Cytat:

    Chciałbym właśnie dowiedzieć się od was jakie są wady takiego rozwiązania

    Dr.Vee podał dwie potencjalne wady (podkreślenie moje):
    Dr.Vee napisał:

    GCC wspiera standard ISO C99, który dopuszcza takie deklaracje (nazywa się to VLA = Variable Length Array). Ponieważ kompilator C++ w GCC (czyli g++) korzysta z tego samego generatora kodu, to VLA są w nim wspierane również w C++, choć de facto nie są częścią standardu.

    Akurat w GCC VLA są alokowane na stosie (choć nie jest to wymaganie VLA). Jest to znacząca różnica, gdyż pamięć dla tablic alokowanych przez new domyślnie pochodzi ze sterty


    Brak przenośności kodu i ograniczona przestrzeń dostępna na stosie.
  • #25 7235771
    malum
    Poziom 23  
    Posty: 883
    Pomógł: 1
    Ocena: 141
    jestam napisał:

    Brak przenośności kodu i ograniczona przestrzeń dostępna na stosie.


    Jeśli chodzi o przenośność kodu to argument odrzucam, bo jest to sprzeczne z ewolucją programu - po prostu niech autorzy programów, któe nie obsługują takiej konstrukcji ją dopiszą.
    Drugi argument jestem skłonny zaakceptować, ale interesują mnie dokładne dane. Jak mam rozumieć sterty są nieograniczone, a stosy ... no właśnie, jaka jest górna granica?
  • #26 7237172
    jestam
    Specjalista Automatyk
    Posty: 1799
    Pomógł: 210
    Ocena: 145
    Cytat:

    Jeśli chodzi o przenośność kodu to argument odrzucam, bo jest to sprzeczne z ewolucją programu - po prostu niech autorzy programów, któe nie obsługują takiej konstrukcji ją dopiszą.


    Czy pisząc "program" masz na myśli "kompilator"? Brak przenośności kodu to nie argument, to fakt. Jeżeli dla Ciebie nieistotny - Twoje prawo.

    Cytat:

    Jak mam rozumieć sterty są nieograniczone, a stosy ... no właśnie, jaka jest górna granica?


    Google! Nie ma rzeczy nieograniczonych w informatyce. Rozmiar sterty jest ograniczony miejscem w pamięci fizycznej i pliku wymiany.

    http://msdn.microsoft.com/en-us/library/ms686774(VS.85).aspx: "The default stack reservation size used by the linker is 1 MB"
    http://blogs.technet.com/markrussinovich/archive/2009/07/08/3261309.aspx
  • #27 7237194
    malum
    Poziom 23  
    Posty: 883
    Pomógł: 1
    Ocena: 141
    [quote="jestam"]
    Cytat:

    Nie ma rzeczy nieograniczonych w informatyce. Rozmiar sterty jest ograniczony miejscem w pamięci fizycznej i pliku wymiany.


    No więc też argument mało wartościowy, skoro i stos i sterta mają swoją granicę
  • #28 7238899
    jestam
    Specjalista Automatyk
    Posty: 1799
    Pomógł: 210
    Ocena: 145
    Może poczytaj trochę, choćby z linków które podałem. Zastanów się gdzie leży granica pojemności sterty, a gdzie stosu i do czego używa się każdego z nich.
  • #29 7239242
    malum
    Poziom 23  
    Posty: 883
    Pomógł: 1
    Ocena: 141
    jestam napisał:
    Może poczytaj trochę, choćby z linków które podałem. Zastanów się gdzie leży granica pojemności sterty, a gdzie stosu i do czego używa się każdego z nich.


    Obrazki ładne, niestety reszta nie po polsku, więc może krótkie streszczenie w języku ojczystym?

Podsumowanie tematu

LABEL_AI_GENERATED
Dyskusja dotyczy sposobów tworzenia tablic dynamicznych dwuwymiarowych w C++. Pierwszy sposób to alokacja tablicy wskaźników do tablic jednowymiarowych (int** tab = new int*[w]; z pętlą alokującą kolejne tablice int[k]), co jest zgodne ze standardem C++ i umożliwia dynamiczne ustalanie rozmiaru tablicy w czasie działania programu. Drugi sposób, czyli deklaracja tablicy int tab[w][k]; z rozmiarami określanymi w czasie wykonania programu, jest niezgodna ze standardem ISO C++, ponieważ standard nie dopuszcza zmiennych rozmiarów tablic (VLA) w C++. Jednak niektóre kompilatory, takie jak GCC (używany przez DevC++), wspierają tę konstrukcję jako rozszerzenie (VLA z C99), alokując tablicę na stosie. W praktyce drugi sposób działa w niektórych środowiskach, ale jest nieprzenośny i może prowadzić do problemów z zarządzaniem pamięcią, gdyż pamięć na stosie jest ograniczona (domyślnie około 1 MB w Windows). Pierwszy sposób wymaga jawnego zwalniania pamięci za pomocą delete[], natomiast drugi sposób nie wymaga ręcznego zwalniania, gdyż pamięć jest automatycznie zwalniana po wyjściu z zakresu. Zaleca się stosowanie dynamicznych tablic alokowanych na stercie lub użycie kontenerów STL (np. std::vector), które zapewniają bezpieczeństwo i przenośność kodu. Dyskusja podkreśla różnice między tablicami statycznymi, dynamicznymi i wskaźnikami oraz wskazuje na ograniczenia i zalety obu podejść.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA