Bugün öğrendiğim bir bilgiyi aktarıyorum: İşlevler 'int[] sayılar...' ve 'int[] sayılar' ile yüklenebiliyorlarmış.
Belirsiz sayıda ama aynı türden parametre alan işlevler o parametreleri dilim olarak görürler:
import std.stdio;
void main()
{
auto s = S(-1, 0, 1, 10, 42); // <-- Normal parametre değerleri
}
struct S
{
this(int[] sayılar...) // <-- Dilim olarak görür
{
writefln("%((%s)%| %)", sayılar);
}
}
Çağrılan yerde dilim söz dizimi kullanılmadığı halde işlev tarafında dilim görülür. Kurucu işlev sayıları parantez içinde yazdırıyor:
'
(-1) (0) (1) (10) (42)
'
Buraya kadar bir sorun yok çünkü sayıları yazdırdık ve işimiz bitti. Ancak, bu forumda daha önce de konuşmuş olduğumuz gibi, burada önemli bir ayrıntı var: Parametre olarak görünen dilim, program yığıtında oluşturulur. Dolayısıyla, bir yapı (veya sınıf) üyesine atansa ömrü çoktan bitmiş olabileceğinden hataya neden olur.
Bu sefer, aldığımız dilimi bir üyeye atayalım ve sonra kullanalım:
import std.stdio;
S S_yap()
{
return S(-1, 0, 1, 10, 42);
} // <-- UYARI: Oluşturulan dilimin yaşamı bu noktada sona erer
struct S
{
int[] sayılar;
this(int[] sayılar...)
{
this.sayılar = sayılar; // <-- Sonradan kullanmak üzere saklıyoruz
}
void kullan()
{
writefln("%((%s)%| %)", sayılar);
}
}
void main()
{
auto s = S_yap();
s.kullan();
}
s'nin üyesi olan 'sayılar' çoktan sonlanmış olan elemanları gösterdiklerinden çıktısı şunun gibi bozuk olabilir:
'
(1882273040) (32767) (4203658) (0) (11)
'
Yukarıdaki hatalı sonuca düşmemek için 'int[] sayılar...' parametresinin .dup ile kopyalanması gerekir. Bunun bir masrafı olduğu açık...
İşin garibi, 'int[] sayılar...' söz dizimi normal dilimleri de kabul eder. Dolayısıyla, S_yap() içindeki S açıkça dilim ile oluşturulsa sorun yoktur:
return S([-1, 0, 1, 10, 42]); // <-- Yaptığımız tek değişiklik
Açıkça oluşturulan dilimin yaşamı çöp toplayıcı tarafından yönetildiğinden döndürülen S nesnesi yaşadığı sürece yaşamaya devam eder. Güzel:
'
(-1) (0) (1) (10) (42)
'
Dolayısıyla, çağıran açıkça dilim verdiğinde .dup ile kopyalamaya gerek yoktur.
Buna rağmen, ben bu güne kadar hep .dup ile kopya almak gerektiğini düşünüyordum. Bugün öğrendiğime göre, 'int[] sayılar...' ile 'int[] sayılar' yüklenebiliyormuş. Belirsiz sayıda parametre birincisine, açıkça dilim ikincisine gidiyormuş. Dolayısıyla, hangisinde .dup ile kopya almamız gerektiğini bilebiliyoruz:
import std.stdio;
S S_yap()
{
return S(-1, 0, 1, 10, 42);
}
struct S
{
int[] sayılar;
this(int[] sayılar...)
{
/* Belirsiz sayıda parametre (variadic) ile çağrıldık. Bu dilim
* program yığıtındadır. Hataya düşmemek için kopyalamamız gerek: */
this.sayılar = sayılar.dup;
}
this(int[] sayılar)
{
/* Açıkça dilim ile çağrıldık kopyalamaya gerek yok. */
this.sayılar = sayılar;
}
void kullan()
{
writefln("%((%s)%| %)", sayılar);
}
}
void main()
{
auto s = S_yap();
s.kullan();
auto s2 = S([ 1000, 2000 ]);
s2.kullan();
}
Her iki kullanım da hatasız:
'
(-1) (0) (1) (10) (42)
(1000) (2000)
'
Ali
--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]