2009-07-13 16 views
8

Mam taki podstawowy problem w Delphi, nie mogę go rozwiązać.Jak skopiować tablicę?

mój kod:

Uwaga: Datar jest lokalny w poniższych metod, ale zazwyczaj jest to klasa var.Just do koncepcji, że to lokalny.

class procedure TCelebrity.BeginRead(var input:Array of byte); 
var DataR:Array of byte; 
begin 
    VirtualFree(@DataRead,High(DataRead),MEM_RELEASE); 
    SetLength(DataR,Length(input)); 
    Move(input,DataR,Length(input)); 
end; 

To kompiluje, ale po wykonaniu funkcji Move() DataR = nil.

Druga próba:

class procedure TCelebrity.BeginRead(var input:Array of byte); 
var DataR:Array of byte; 
begin 
    VirtualFree(@DataRead,High(DataRead),MEM_RELEASE); 
    SetLength(DataR,Length(input)); 
    DataR := Copy(input,0,Length(input)); 
end; 

nie skompilować na all.Error w trzeciej linii (Datar: = Copy (wejście ....) mówiąc: "niezgodne typy"

Gdzie jest. ?!

Odpowiedz

7

problem wszyscy są Array of byte Dlaczego nie użyć do

SetLength(DataR,Length(input)); 
for i:=Low(input) to High(input) do 
    DataR[i]:=input[i]; 

BTW: jeśli chcesz są tablice podając jako parametr, należy zadeklarować je jako typ, np:

type 
    TMyArray = array of byte; 

i używać TMyArray jako parametry typu.

Edytuj: Powiadomiono mnie o niższej wartości. W moim oryginalnym wpisie było to dla i: = 0, ale i: = Low (input) jest bezpieczniejsze i bardziej czyste.

+0

Mam jedno pytanie. VirtualFree zawsze zwraca wartość false, więc w jaki sposób mogę zwolnić pamięć obecnie używaną z DataR? Uwaga DataR nie jest lokalna, ale klasa var w oryginalnym kodzie. Z góry dziękujemy za odpowiedź! –

+0

Nie, nie masz darmowych prostych tablic. Takie tablice są automatycznie zwalniane (na przykład, gdy twoja klasa jest niszczona). Uwaga: jeśli masz tablicę odniesień do obiektów, musisz ręcznie zwolnić te obiekty, ponieważ tylko tablica zostanie zwolniona przez Delphi. – smok1

+0

Należy również pamiętać, że SetLenght ponownie przydziela całą tablicę, więc należy unikać intensywnego korzystania z tej procedury. Po wydłużeniu tablicy przy użyciu funkcji SetLength obecna zawartość pozostaje nienaruszona, jednak po jej skróceniu część zawartości zostanie utracona. – smok1

2

Spróbuj:

class procedure TCelebrity.BeginRead(var input:Array of byte); 
var DataR:Array of byte; 
begin 
    VirtualFree(@DataRead,High(DataRead),MEM_RELEASE); 
    SetLength(DataR,Length(input)); 
    Move(input[0],DataR,Length(input)); 
end; 
+0

Zrobiłem, to nie działa. –

8

spróbować tej

type 
    TByteDynArray = array of Byte; 

function CopyData(const Input:array of Byte):TByteDynArray; 
begin 
    SetLength(Result, Length(Input)); 
    Move(input[0], Result[0], Length(Input)); 
end; 
+5

Prawidłowa odpowiedź. ale aby była to * dobra * odpowiedź, powinieneś wyjaśnić * dlaczego * twoje zmiany są znaczące. W przeciwnym razie to tylko magiczne zaklęcie. –

+3

Popraw mnie, jeśli się mylę, ale warto zauważyć, że działa to tak, jak napisano dla 'tablicy Bajta'. Jeśli tablica była inna, powiedz 'tablica Integer', to potrzebujesz' Move (input [0], Result [0], Length (Input) * SizeOf (Integer)) '. Tylko mówię. –

+0

@Rob Kennedy: Move() w delphi jest podobne do memcpy()/memmove() w C – dns

1

procedury Move nie ruszy fragment pamięci. Kopiuje Count bajty. W ten sposób otrzymasz dwie różne identyczne tablice: Input i DataR.

procedure CopyData(const Input: Array of Byte); 
var 
    DataR: Array of Byte; 
begin 
    SetLength(DataR, Length(Input)); 
    Move(Input[0], DataR[0], SizeOf(Byte)*Length(Input)); 
end; 

P.s. w przypadku tablic statycznych można użyć SizeOf (Input) zamiast SizeOf (Byte) * Length (Input). Zamiast Byte może być inny typ danych.

+0

dlaczego nie używać SizeOf (Wejście [0]) zamiast zakodowanego typu danych? –