Dynamiczna tablica dwuwymiarowa - problem z inicjalizacją

2012-06-22 14:40
0

#include <iostream>
using namespace std;
int main()
{
    unsigned short W, K; //W - liczba wierszy
    cin >> W >> K;       //K - liczba kolumn
    int **tab=new int *[W];
    cout << "\n";
    for(unsigned short i=0;i<K;i++)
    {
        tab[i]=new int[K];
    }
    unsigned short n=1;
    //inicjalizacja
    for(unsigned short i=0;i<W;i++)
    {
        for(unsigned short j=0;j<K;j++)
        {
            tab[i][j]=n;
            n++;
        }
    }
    //wyswietlanie
    for(unsigned short i=0;i<W;i++)
    {
        for(unsigned short j=0;j<K;j++)
        {
            cout << tab[i][j] << "\t";
        }
        cout << "\n\n";
    }
    //usuwanie
    for(unsigned short i=0;i<K;i++)
    {
        delete [] tab[i];
    }
    delete [] tab;
    return 0;
}

Gdy podaję na wejście liczby o równych wartościach, np. 5 i 5, to jest ok (http://ideone.com/HYp19). Problem zaczyna się w przypadku różnych wartości, np.:

#5 i 7, wtedy Windows raportuje błąd po wyświetleniu zawartości tablicy. Przykład: http://ideone.com/FnBlr
#7 i 5, wtedy jest błąd jest raportowany przy inicjalizacji tablicy. Przykład: http://ideone.com/9wj4b
#9 i 6, podobnie jak w poprzednim punkcie.

Program kompiluje się i uruchamia bez problemu.


edytowany 1x, ostatnio: cichociemny, 2012-06-22 14:44

Pozostało 580 znaków

2012-06-22 15:04
cin >> W >> K;       //K - liczba kolumn
int **tab=new int *[W];
cout << "\n";
for(unsigned short i=0;i<K;i++) // powinno byc do W, bo tyle na poczatku alokujesz
{
    tab[i]=new int[K];
}

Dobre, rzeczywiście to miałem źle. Nadal jest problem http://ideone.com/6auF7 - cichociemny 2012-06-22 15:28
To samo masz w pętli usuwania tablicy – też powinno być do W. - rincewind 2012-06-22 15:34

Pozostało 580 znaków

2012-06-22 16:30
0

Jest ok, rozumiem błąd. Teraz pytanie czy dobrze rozumiem napisany przez siebie kod :)
Chodzi mi o trochę trudniejsze fragmenty.

int **tab=new int *[W];

Od lewej. Tworzę wskaźnik na tablicę wskaźników na tablicę W-wymiarową.

for(unsigned short i=0;i<K;i++){ tab[i]=new int[K];}

Każdemu elementowi tablicy W-wymiarowej przypisuję wskaźnik na nową tablicę K-wymiarową.
W ten sposób uzyskuję dynamiczną tablicę dwuwymiarową.

for(unsigned short i=0;i<K;i++){delete [] tab[i];}

Usuwam wcześniejsze przypisania wskaźników do tablicy W-wymiarowej.

delete [] tab;

Usuwam wskaźnik na tablicę wskaźników na tablicę W-wymiarową.


Pozostało 580 znaków

2012-06-22 18:41
1
cichociemny napisał(a):
int **tab=new int *[W];

Od lewej. Tworzę wskaźnik na tablicę wskaźników na tablicę W-wymiarową.

Tworzysz wskaźnik do wskaźnika na int nazwany tab, alokujesz tablicę wskaźników (int*) długości W i inicjalizujesz tab tak, aby wskazywał na początek zaaokowanej tablicy.

cichociemny napisał(a):
for(unsigned short i=0;i<K;i++){ tab[i]=new int[K];}

Każdemu elementowi tablicy W-wymiarowej przypisuję wskaźnik na nową tablicę K-wymiarową.
W ten sposób uzyskuję dynamiczną tablicę dwuwymiarową.

Każdemu z W wskaźników do int w tablicy tab przydzielasz tablicę int długości K.

cichociemny napisał(a):
for(unsigned short i=0;i<K;i++){delete [] tab[i];}

Usuwam wcześniejsze przypisania wskaźników do tablicy W-wymiarowej.

Zwalniasz pamięć przydzieloną w poprzedniej pętli do każdego z elementów tablicy tab. Każdy z tych elementów jest wskaźnikiem na int i wskazuje blok pamięci przydzielony operatorem new[] – każdy z tych bloków to tablica int[K].

cichociemny napisał(a):
delete [] tab;

Usuwam wskaźnik na tablicę wskaźników na tablicę W-wymiarową.

Zwalniasz główną tablicę tab.

Ważna jest tu kolejność, bo tak naprawdę tab jest wskaźnikiem na początek bloku pamięci, podobnie jak każdy element w tab. Jeśli zwolnisz od razu główną tablicę, stracisz możliwość odwołania się do podtablic, co skutkuje memleakiem.


Pozostało 580 znaków

Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0