[C++] Przekazywanie tablic wielowymiarowych do funkcji

Cześć,

mam problem dotyczący działania tablic w C++. Otóż chcę do funkcji przekazać statyczną tablicę używając referencji, tak by móc pracować na oryginalne. Dowiedziałem się, że do tego wcale nie jest potrzebna referencja. Ok, idąc dalej: przypuśćmy, że mam tablicę o wymiarach 5x5 i chcę ją przekazać do funkcji bez podawania ilości jej elementów. O przekazywaniu przeczytałem już całą masę wątków, ale większość z nich opiera się na tablice jednowymiarowe, przy których problemu nie ma. Do tablicy dwuwymiarowej użyłem czegoś takiego:

template 

unsigned int wypisz(int(&TAB)[n][m])

{

//kod

}

Wydaje mi się to jednak sposób nieszczególnie poprawny.

Wiem, że mogę to zrobić poprzez tablice dynamiczne, ale nie do końca mogę zrozumieć w nich rolę wskaźników. Czytałem także, że tablic statycznych się praktycznie nie używa. Prawda to? W jaki sposób najlepiej jest pracować na tablicach?

W C++ nie przekazuje się tablicy w argumentach tylko wskaźnik na pierwszy element.

Zapis typu

int foo(int x[]);

jest lukrem składniowym i znaczy dokładnie

int foo(int *x);

Tablica wielowymiarowa to tablica, której elementami są tablice, np.

int tab[4][6];

to 4elementowa tablica 6elementowych tablic intów. Przy przekazywaniu takiej tablicy do funkcji można pominąć tylko pierwszy rozmiar, pozostałe muszą być podane, np.

int foo(int x[][6]);

co znaczy to samo, co

int foo(int (*x)[6]);

Drugiego rozmiaru (i następnych) nie można pominąć, ponieważ określa on typ elementu tablicy. Aby się pozbyć sztywnego rozmiaru można np. używać tablicy wskaźników, gdzie każdy wskaźnik wskazuje na pierwszy element podtablicy (poszczególne podtablice mogą wtedy różnić się długością nawet między sobą) lub używać tablic jednowymiarowych a wielowymiarowość symulować odpowiednio wyliczając indeksy (dokładnie tak robią kompilatory, ponieważ pamięć jest adresowana liniowo). Do obliczania indeksu używa się wzoru i = y * w + x ; gdzie: w - szerokość tablicy dwuwymiarowej x, y - współrzędne w tablicy dwuwymiarowej i - indeks w tablicy jednowymiarowej.

void wypisz(int w, int h, int *tab)

{

	for(int y = 0; y < h; ++y)

	{

		for(int x = 0; x < w; ++x)

			printf("%d; ", tab[y * w + x]);

		printf("\n");

	}

}

int t[9][5];

wypisz(5, 9, &tab[0][0]);

Co do wskaźników to polecam: http://www.youtube.com/watch?v=bewTJaboGIw, http://www.youtube.com/watch?v=1I0ObS-RQvQ, http://www.youtube.com/watch?v=ICrBkVxkdVI, http://www.youtube.com/watch?v=mqCULVvaS1c, http://www.youtube.com/watch?v=YvA8tNm0FbA, http://www.youtube.com/watch?v=B7x-RWNGhgc, http://www.youtube.com/watch?v=_5pfrvlY_cA, http://www.youtube.com/watch?v=OuJMvfwblb0, http://www.youtube.com/watch?v=ByzWW_IiGU0, szczególnie #9 ponieważ są tam omówione tablice dwuwymiarowe :slight_smile:

Prawda. Tablic statycznych zbyt często się nie używa bo jest znacznie mniejsza liczba przypadków kiedy z góry znamy rozmiar tablicy na jakiej będziemy pracować, a dodatkowo zakładanie stałego rozmiaru takiej tablicy (w czasie wykonania programu) zmniejsza szanse na ponowne wykorzystanie kodu. W C/C++ wszystkie tablice są przekazywane przez referencje, jeśli chciałbyś przekazać kopie całej tablicy to musisz ją sobie skopiować ręcznie. Najlepiej pracować na odpowiadającej Tobie strukturze danych, np. vector.

tutaj masz przykład wielowymiarowych tablic na vectorach:

http://www.cplusplus.com/forum/articles/7459/

Nie lepiej zrobić dynamiczną tablicę?

Przekazujesz ją wtedy jako np. int **tablica;

@Marcin1147, tym razem chciałem się przekonać jak to jest z tablicami statycznymi. Zawsze używałem dynamicznych, a próbując zastosować statystyczne podobnie jak dynamiczne, otrzymywałem błędy. Widzę jednak, że lepiej zostać przy dynamicznych.

P.S. Dzięki Rolek0 i EnterBioS :wink:

Btw. Czy ten sposób, który podałem w pierwszym poście (do uniknięcia podawania ilości elementów) nie jest grzechem programistycznym? Takie praktyki się stosuje?

No, wiesz… Grzechem nie jest, do tego są szablony/makra przecież ale są lepsze metody jak np. właśnie tablice dynamiczne.

Okej, wszystko już jest jasne. Dzięki za pomoc :wink: