BURDA başlayan tartışmayan burdan devam...
On Tuesday, 11 January 2022 at 08:33:20 UTC, Ferhat Kurtulmuş wrote:
Salih, tam olarak ne elde etmek istediğini anlamadım. Ama aşağıdaki örnek üzerinden bir şeyler anlatmak istedim. Hatalı olduğum bir yer varsa muhtemelern Ali abimiz düzeltecektir.
Sınıflar d'de referans tipleridir ve aslında arkasında (T*) gibi pointerlar çalışmaktadır. Bu yüzden örnekte A'nı elemanlarını azaltalım veya yeni elemanlar ekleyelim, her zaman aynı A.sizeof değerinini (size_t tipinden byte değeri) alırız. Struct'larda böyle değil. Ha, structlarda bir de alignment devreye girmekte, Ali abinin kitabında alignment konusuna yer verilmiş olmalı. Konumuza dönelim. A sınıfı için A.sizeof bir pointer'ın kapladığı alana karşılık geliyor. D'de sınıf instance'ının byte olarak hafızada kapladığı alanın değerini ise __traits(classInstanceSize, A) ile öğreniyoruz. İşte buradaki değer, yeni sınıf üyeleri ekledikçe veya sınıf üyelerini çıkardıkça değişir.
Gelelim class üye metodlarına. Bunları ekleyip çıkarmak classInstanceSize'ı etkilemez. Çünkü onlar sınıf tarafından aslında kapsanan fonksiyonlar değiller. Sınıf üye metodları, virtual table'da[1] o sınıfın instance'ı ile ilişkilendirilen fonksiyon pointerlarından ibaretler ve class instance boyutuna katkıları yoktur. Ancaaaaak, aşağıdaki örnekte A sınıfının bir de var4 adında bir fonksiyon pointer üyesi bulunmakta. Bunun gibi üye fonksiyon pointerları class instance boyutunu etkilerler. Çünkü o bir pointer ve bir pointerın kaplayacağı hafıza kadar yer kaplar (bende 8 byte). Sınıf üyelerini benim örneğimde yoruma alarak veya kendin yeni üyeler ekleyerek nasıl bir çıktı alıyorsun deneyip görebilirsin.
Selamlar.
1: https://dlang.org/library/object/type_info__class.vtbl.html
import std;
class B {
}
class A {
int var1;
ubyte var2;
B var3;
void function() var4;
void f1(){}
}
void main()
{
pragma(msg, A.sizeof);
writeln(__traits(classInstanceSize, A));
}
Ferhat Hocam, geç cevap yazdığım için kusura bakmayın; ailecek korona olduk da (!) şu an toparladık şükür...:)
Konu içinde tekrar bir konu oluşturduğum için telafi amaçlı buradan devam edelim ve hızlıca asıl konumuza dönelim...
Aşağıdaki kodu siz de denemek isterseniz her sınıf sonuna düştüğüm notlardaki değerleri bulabilirsiniz. Hatta kod, yapılarda da çalışıyor. Tek yapmanız gereken, main()'deki ilk satırın remark'ını açmak. Sınıflara geçmeden önce yapılara şöyle pratik şekilde dokunalım:
T.sizeof() ile edindiğimiz bilgiler sıradan çünkü her int, bize 4 bayta maloluyor. Öyle ya int, 32 bit bir değer ve short'da, bu yarı yarıya düşecekken long'da, ikiye katlanacaktı. a4.Node için de anlaşılmayacak bir şey yok çünkü kendini de işaret eden bir işaretçi kendi gibi 8 bayt yer kaplıyor, değil mi?
Class'lara geldiğimizde ise extern(C) ayrımı var. Ali hocam düzeltirse sevinirim; anladığım kısaca şu:
D'de sınıflar için ekstra bir şeyler var ve eğer kodunuz müsaitse (sanırım sınıf, D olanaklarını içermemeli) daha az yer kaplaması için tercih edilebiliyor.
Aslında sınıflar için de anlaşılmayacak bir şey yokmuş. Açık söylemek gerekirse şimdi farkettim. Çünkü yapıya göre 16 bayt ekstrası var. O da Object'den türediği için. Neticede kod yazarken görmediğimiz üyeleri var. Yani extern(c) değilse formül şu 16 byte + (üyeAdeti * türBoyutu)
a4.Node için son bir not: Yapılar için anlaşılmayacak bir şey yok dedim ama neden boyutu 24/32LU kalıyor? Sanırım henüz new ile kurulmamış bir sınıf işaretçisi olduğu için, olabilir mi?
/* extern / class / struct */
//extern (C++)
class Point {
int x, y;
} /* 16LU / 24LU / 8 byte */
//extern (C++)
class Line {
int x, y, z;
} /* 20LU / 28LU / 12 byte */
//extern (C++)
class Rectangle {
Point XY, EB;
} /* 24LU / 32LU/ 16 byte */
//extern (C++)
class Node {
Point item;
Node * next;
} /* 24LU / 32LU / 16 byte */
import std.stdio;
alias a1 = Point;
alias a2 = Line;
alias a3 = Rectangle;
alias a4 = Node;
void main()
{
// a1 test;/*
__traits(classInstanceSize, a1).writeln(" LU");
auto test = new a1;//*/
write(typeof(test).stringof);
writeln(": ",typeof(test).sizeof, " bytes");
}
On Tuesday, 11 January 2022 at 08:33:20 UTC, Ferhat Kurtulmuş wrote:
>Sınıflar d'de referans tipleridir ve aslında arkasında (T*) gibi pointerlar çalışmaktadır. Bu yüzden örnekte A'nı elemanlarını azaltalım veya yeni elemanlar ekleyelim, her zaman aynı A.sizeof değerinini (size_t tipinden byte değeri) alırız. Struct'larda böyle değil. Ha, structlarda bir de alignment devreye girmekte, Ali abinin kitabında alignment konusuna yer verilmiş olmalı.
Hocam böyle sonuç almanızın sebebi henüz sınıfı new ile kurmadan test etmeniz olabilir mi? Ayrıca Ali hocanın yapılardaki yaslama mevzusunu araştıracağım. Acaba bellek yönetimi konusunda çok faydası var mı?
Ali hocam, yoksa bu analizler ile çok kastırmayıp std.bitmanip ile inanılmaz küçük boyutlarda D yapılarını oluşturup keyfimize bakabilir miyiz?
Herkese teşekkürler...