Thread overview
Uye eleman hayata getirme listesinin D'de gerekmemesi (Member initlization list )
Jan 03, 2018
kerdemdemir
Jan 03, 2018
kerdemdemir
January 03, 2018

C++ kodu yazarken aklima geldi. Eger D deki gibi kurucu islevin(ctor) icinde ilk atama hayata getirme(initilization) oldugunu D derleyici cozebiliyorsa bunu C++ derleyicileri neden yapmiyorlar. Neden M.I.L gibi ozel bir kurala ihtiyac duyuyolar?

Biraz ornek verip acacak olursam C++:
class A
{
A () : a(5) // :a(5) dizilimini bilmek gerekiyor
{
}
int a;
}

D ise sagolsun :

class A
{
this()
{
a = 5; // Bu bir atama degil D de hayata getirme
}
int a;
}

Bu C++ gecmisine dayanan bir sorunmu yoksa multiple inheritance gibi C++ ozelliklerinin getirdigi bir zorunluluk mu ?

Erdemdem

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

January 03, 2018

Nedenini düşünmemiştim ama herhalde kurucu işleve girildiğinde anlamlı değerleri olsun diye bir ilkleme alanı düşünülmüş olmalı. D'de olduğu gibi ilk değer verilmesi yeterli olmazdı çünkü üyelerin değerlerini her nesne için aynı olması sık rastlanılan bir durum değil.

D'de durum farklı: C ve C++'ın aksine, her değişken otomatik olarak ilklenir (D'nin doğru kararlarından birisi). (İstenmiyorsa '= void' ile ilklenmemiş halde bırakılabilir.) O yüzden, ilk değerlerin tür içinde verilmesi sorunlu değil. Yapılarda ilk değer, yani 'BenimYapım.init' değeri, gereken adet bayttan oluşur. Bu ilk değer, nesne oluşturulduğunda nesnenin bulunduğu yere toptan kopyalanır.

Ancak, gösterdiğin "bir atama degil D de hayata getirme" örneği sınıflar için doğru değil. Hatta, yapılar için bile doğru değil çünkü açıkça değer atıyorsun. Sanırım üye tanımındaki atamayı düşünerek yazmış olmalısın:

O kodun assembly'sine batığımızda (D ile gelen obj2asm programı kullanılabilir) yapının ilk değerinin bir yazmaca (RDX) yerleştirildiğini ve writeln'ın o değerle çağrıldığını görüyoruz (ldc2 ile ve -O5 seçeneği ile derledim):

struct S {
   int a = 0x55555555;
   int b = 0xaaaaaaaa;
}

//...
   auto s = S();
   writeln(s);

'
mov RDX,0AAAAAAAA55555555h
mov ESI,0Ah
mov RDI,RBX
call _D3std5stdio4File23__T5writeTS6deneme1STaZ5writeMFNfS6deneme1SaZv@PLT32
'
Yani, dediğin gibi, yapı oluşturulurken üyelere teker teker atama yapılmıyor.

Sınıflarda öyle değil:

class C {
   int a = 0x55555555;
   int b = 0xaaaaaaaa;

   void foo() {
       writeln(a, b);
   }
}
/...
   auto c = new C();
   c.foo();

Görüldüğü gibi, ayrı ayrı atanıyor:
' mov EDX,0AAAAAAAAh
mov ECX,055555555h
mov RDI,RBX
call _D3std5stdio4File16__T5writeTiTiTaZ5writeMFNfiiaZv@PLT32
'
İşin güzeli, o ilk değerler fazladan masraf getirmiyor. Örneğin, bir kurucu işlev eklesek ve üyelerden birisine kendimiz farklı bir değer atasak, o üyeye iki kere atanmıyor.

   this() {
       b = 0x11111111;
   }

Artık 0xaaaaaaaa ataması yok:
'
mov EDX,011111111h
mov ECX,055555555h
mov RDI,RBX
call _D3std5stdio4File16__T5writeTiTiTaZ5writeMFNfiiaZv@PLT32
'
Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

January 04, 2018

Ben sunu kastedmistim

https://dlang.org/spec/class.html#field-init

Diyorki ; Inside constructor, the first instance field assignment is specially handled for its initialization.

Bu cumleden ben sanki atama degilde hayata getirme olmasi gerektigini cikariyorum. Acaba yanlis mi anliyorum veya yanlis mi turkce kelimeler sectim acaba anlatirken.

Acaba yapilar icin ayri kurallar mi var kurucu islev icin? O zaman biraz karisik sanki .

Abi ben sadece pic denen bir mikro controlor'e assembly yazmistim, bambaska birseydi ne yazikki cok zayifim bu konuda ama sen anlatinca anladim. Boyle senin gibi anlatan bir kaynak biliyormusun assembly icin acaba ?

Erdemdem

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

January 04, 2018

Evet, yapılar için kurallar farklı: Örneğin, default constructor yazmak bile yasak. Bunun nedeni, D'de yapıların ilk değerleri derleme zamanında bilinen değer türü olmaları.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]