2009-04-03 7 views
9

Zaten referansla geçen ve bu yüzdenDelphi'de bir diziyi referans alarak nasıl geçersiniz?

procedure test(var x:integer); 
begin 
    x:=x+5; 
end; 

nedenle yukarıdaki kod güncellemeleri 5 referans ile ilgili okumak. Bir diziyi referans olarak güncelliyor olsaydım, var X: blah dizisini bildirebilirdim ... bazı hata hataları vardı ve yalnızca veriye işaretçi için veri türünü kullanmam gerekip gerekmediğini öğrenmek istedim. işaretçi her zaman int ... sadece bu yüzden benim referansta geçirerek yaptığımı mı yoksa kodumdaki başka bir şey mi olduğunu biliyorum.

cevap

19

Dinamik diziyi bir var olmayan parametre olarak iletirseniz, derleyici bir kopya oluşturacaktır. Aşağıdaki küçük kod örneği, form başlığında 37/42 görüntülendiğini göstermektedir. Biz oluşturulan Çevirici koduna bakarsak

procedure IncArray1(data: array of integer); 
var i : integer; 
begin 
    for i := Low(data) to High(data) do 
    data[i] := data[i] + 5; 
end; 

procedure IncArray2(var data: array of integer); 
var i : integer; 
begin 
    for i := Low(data) to High(data) do 
    data[i] := data[i] + 5; 
end; 

procedure TForm8.FormCreate(Sender: TObject); 
var 
    data: array of integer; 
begin 
    SetLength(data, 1); 
    data[0] := 37; 
    IncArray1(data); 
    Caption := IntToStr(data[0]); 
    IncArray2(data); 
    Caption := Caption + '/' + IntToStr(data[0]); 
end; 

, IncArray1 yığınına

004552B4 8BCA    mov ecx,edx 
004552B6 85C9    test ecx,ecx 
004552B8 7807    js $004552c1 
004552BA 8B1C88   mov ebx,[eax+ecx*4] 
004552BD 49    dec ecx 
004552BE 53    push ebx 
004552BF 79F9    jns $004552ba 
004552C1 8BC4    mov eax,esp 

ile bu kod kopyalar kaynak dizisi başlar ve (= Adres saklanan birinci elemanın adresine eax ayarlar son basamağından sonra yığın işaretçisi. Yığın, son öğe ile başlar (kod, IncArray1 çağrıldığında edx Yüksek (veri) içerir) ve eleman 0'a gelinceye kadar (okuma öğesi; itme öğesi; eksiltme indeksi) tekrarlanır.

IncArray2, böyle bir kod. Arayan kişi, IncArray2 ve IncArray2'yi çağırmadan önce verilerin adresini eax kaydına kaydeder.

Herhangi bir nedenle 'var' kullanmak istemiyorsanız, verilerinizin adresini yönteminize iletebilirsiniz. Ancak, parametre beyanında sözdizimi 'verisini: tamsayı dizisini' kullanamadığınızdan, verileriniz için bir tür bildirmeniz gerekir. Ve yöntemde her yerde 'veri' yerine 'data ^' kullanmanız gerekir.

type 
    TData = array of integer; 
    PData = ^TData; 

procedure IncArray(data: PData); 
var i : integer; 
begin 
    for i := Low(data^) to High(data^) do 
    data^[i] := data^[i] + 5; 
end; 

procedure TForm8.FormCreate(Sender: TObject); 
var 
    data: TData; 
begin 
    SetLength(data, 2); 
    data[0] := 37; 
    IncArray(@data); 
    Caption := IntToStr(data[0]); 
end; 

Delphi 2007.

+0

Tamam, bunu yapmanın bir yolu var, referans yoluyla üzerinde çalışmak istediğim geniş bir dizim var. diziyi kopyalamak comptationaly pahalı olmaktan çok uzaktır. – Arthur

+0

Evet, tıpkı IncArray2'nin yukarıdaki kodda yaptığı gibi - kullanıcı 'var' öneki. – gabr

+0

@gabr, Değişmeyen bir dinamik dizinin kopyalanıp kopyalanmadığını kontrol edebilir misiniz?O dizelerin yazıya kopyalandığını biliyorum. –

6

ile test edilmiştir Gabr cevabı doğrudur ama anahtar nokta ben ayrı bir yayın olarak bunu getireceğim yeterince derin gömüldü:

öncelikle türlerini tanımlayın! Bu özel durumda, derleyici orada bir tamsayı dizisini kabul etti, ancak bunun yalnızca özel bir anlamı olduğu ve bunun beklediğiniz NOT olduğu. Prosedürün tanımında bir tür tanımlamaya yönelik başka herhangi bir girişim başarısızlıkla sonuçlanabilirdi. C aksine

, sen iki şeyi atama aynı inşa edilir AYNI türünü değil, sadece iki tip olarak bunları beyan etmek zorunda uyumlu olmasını istiyorsanız:

Var 
    A : Array [1..4] of Integer; 
    B : Array [1..4] of Integer; 

Begin 
    A := B; 

derlemek olmaz . Aksine:

Type 
    Array4 = array [1..4] of Integer; 

Var 
    A : Array4; 
    B : Array4; 

Begin 
    A := B; 
ve derleyici beklediğiniz şeyi yapar.

+0

Gabr'ın mesajından sonra kodu değiştirmek için kaçmak zorunda kaldım, şimdi söylediğiniz tam konu var, kazık gelmiyor, resmi tipler aynı olacak diyor ahve .. A ve B benim için farklı birimlerde .. ne yapabilirim? – Arthur

+0

A biriminin "kullanır" birim B'yi farz edelim. Paylaşılan türü B biriminde belirtin ve her ikisi de bu tanımı "görebilir". – Argalatyr

+2

Eğer gabr'ın kodunu çalıştırırsanız, ancak TIntArray (TIntArray = tamsayı dizisi) ile değiştirilen tüm "tamsayı dizisi" ile dizge, her zaman referans olarak geçirilir ve veri [0] 37 + 5 + 5 = 49 olur. Bu garip değil mi? –