[ Pobierz całość w formacie PDF ]
.Okreœlenie tego rozmiaru, ijednoczeœnie przydzielenie odpowiedniej iloœci pamiêci, wykonywane jest przezfunkcjê SetLength():Readln(N);.SetLength(A, N);Ostatnia z powy¿szych instrukcji ustala rozmiar tablicy A na N elementów(bior¹c oczywiœcie pod uwagê bie¿¹c¹ wartoœæ zmiennej N).Doln¹ wartoœci¹ graniczn¹ indeksu tablicy dynamicznej jest zawsze zero, tote¿indeksami granicznymi wektora A bêd¹ wartoœci 0 oraz N-1; innymi s³owy, jeœli wczasie wykonania instrukcji SetLength(…) wartoœci¹ N by³o (powiedzmy) 5, to odtej pory tablicê A wykorzystywaæ mo¿na na równi ze „statyczn¹” tablic¹zadeklarowan¹ jakoarray [ 0.4 ] of string;na przyk³ad w taki sposób:A[1] := 'Jestem ju¿ pe³noprawn¹ tablic¹';.Writeln(A[1], A[2]);.Delete(A[3], 1, Length(A[4]))OpóŸniona deklaracja wielkoœci wymiaru (wymiarów) tablicy dynamicznej nie jestjednak¿e jedyn¹ istotn¹ cech¹ odró¿niaj¹c¹ j¹ od tablic „statycznych”.Jejspecyfika wi¹¿e siê równie¿ z dynamicznym przydzia³em pamiêci, dokonuj¹cym siêdopiero w momencie wywo³ania procedury SetLength(); fizyczn¹ reprezentacj¹zmiennej okreœlaj¹cej tablicê dynamiczn¹ (w tym wypadku — zmiennej A) jestwskaŸnik.Tablice dynamiczne nale¿¹ ponadto do zmiennych o kontrolowanym czasie ¿ycia.Oznacza to, ¿e po zakoñczeniu czasu ¿ycia tablicy dynamicznej (która jest np.zmienn¹ lokaln¹ funkcji/procedury) przydzielona do niej pamiêæ jestautomatycznie zwalniana (ang.garbage-collected).Mo¿emy te¿ wymusiæwczeœniejsze wykonanie tej czynnoœci, podstawiaj¹c pod zmienn¹ tablicow¹wartoœæ NIL:A := NIL; // zwolnienie pamiêci przydzielonej dla tablicy dynamicznej AJest to zalecane szczególnie w odniesieniu do du¿ych tablic dynamicznych,których zawartoœæ przesta³a ju¿ byæ potrzebna.Innym mechanizmem charakterystycznym dla tablic dynamicznych jest oszczêdnoœægospodarowania pamiêci¹ na podstawie licznika odwo³añ (podobnie jak wprzypadku ³añcuchów AnsiString).Dwie tablice dynamiczne o identycznejzawartoœci maj¹ w rzeczywistoœci wspóln¹ reprezentacjê pamiêciow¹, a fakt jejwspó³dzielenia jest odzwierciedlany przez wartoœæ licznika odwo³añ równ¹ 2.Ztego faktu wynika pewna niespodzianka.Przyjrzyjmy siê poni¿szemu fragmentowivarA1, A2 : array of Integer;beginSetLength(A1, 4);A2 := A1;A1[0] := 1;A2[0] := 26;.i zgadnijmy, co kryje siê pod elementem A1[0]?Poprawna odpowiedŸ brzmi: 26.Otó¿ przypisanie A2 := A1 jest de factouto¿samieniem tablic A1 i A2, a wspomniana instrukcja dokonuje tylkoprzepisania wskaŸnika oraz zwiêkszenia licznika odwo³añ.Ka¿da zmiana wobrêbie tablicy A1 skutkowaæ bêdzie identyczn¹ zmian¹ w obrêbie tablicy A2 ivice versa — ergo: przypisanie A2[0] := 26 ustala wartoœæ elementu A1[0] na26.Mo¿liwe jest jednak¿e faktyczne powielenie tablicy dynamicznej — do tego celus³u¿y funkcja standardowa Copy().Po wykonaniu poni¿szej sekwencjivarA1, A2 : array of Integer;beginSetLength(A1, 4);A2 := Copy(A1);A1[0] := 1;A2[0] := 26;wartoœæ A1[0] bêdzie równa 1 [7 Podobny efekt da³ o sobie znaæ w momencie, gdyautorzy Delphi 1 zadecydowali, i¿ wszelkie obiekty reprezentowane bêd¹ wprogramie przez wskaŸniki do fizycznej reprezentacji.Od tej pory zwyk³ainstrukcja przypisania pomiêdzy zmiennymi obiektowymi powoduje jedyniepowielenie wskaŸnika do istniej¹cego obiektu, zaœ fizyczne powieleniereprezentacji wykonywane jest w sposób jawny przez metodê Assign() (przyp.t³um.).].Mo¿liwe jest powielenie jedynie wybranego fragmentu tablicy Ÿród³owej.InstrukcjaA2 := Copy (A1, 2,2);wycina z tablicy A1 elementy A1[2] i A1[3], tworz¹c z nich zawartoœæ tablicy A2— identycznie do poni¿szej sekwencji:SetLength(A2,2);A2[0] := A1[2];A2[1] := A1[3];Wielowymiarowe tablice dynamiczne deklaruje siê poprzez zagnie¿d¿anie klauzuliarray of; oto przyk³ad tablicy dwuwymiarowej:varB: array of array of Integer;Wywo³anie procedury SetLength() musi oczywiœcie uwzglêdniaæ liczbê wymiarów, naprzyk³ad:SetLength(B, 5, 7)nadaje tablicy dynamicznej B strukturêarray [ 0.4, 0
[ Pobierz całość w formacie PDF ]