Nesneler neden referans olarak geçiyor?


31

OO üzerinde çalışan genç bir meslektaş, neden ilkel türlerin ya da yapıların zıddı olan her nesnenin referans olarak geçtiğini sordu. Java ve C # gibi dillerin ortak bir özelliğidir.

Onun için iyi bir cevap bulamadım.

Bu tasarım kararının motivasyonları nelerdir? Bu dillerin geliştiricileri, her seferinde işaretçiler ve typedefs oluşturmak zorunda kalmaktan bıktı mı?


2
Java ve C # 'nin neden parametreleri değer yerine referans olarak mı yoksa işaretçi yerine referans olarak mı ilettiğini mi soruyorsunuz?
robert

@Robert, "işaretçi yerine referans" arasında herhangi bir fark var mı? Başlığı 'neden nesne her zaman referans oluyor?' Gibi bir şeyle değiştirmeli miyim?
Gustavo Cardoso

Referanslar işaretçilerdir.
compman

2
@Anto: Bir Java başvurusu, tamamen kullanılan bir C işaretçisiyle tamamen aynıdır (düzgün bir şekilde kullanılır: tip döküm değil, geçersiz belleğe ayarlanmamış, değişmez tarafından ayarlanmamış).
Zan Lynx

5
Ayrıca gerçekten bilgili olmak için, başlık yanlış (en azından .net söz konusu olduğunda). Nesneler referans tarafından iletilmez, referanslar değer olarak iletilir. Bir nesneyi bir yönteme ilettiğinizde referans değeri, yöntem gövdesinde yeni bir referansa kopyalanır. Bence "nesneler referans yoluyla geçiriliyor" u yanlış olduğu halde ortak programcı alıntıları listesine girdi ve yeni başlayanlar için referansların daha zayıf anlaşılmasını sağladı.
SecretDeveloper

Yanıtlar:


15

Temel sebepler şudur:

  • İşaretçiler doğru almak için teknik
  • Bazı veri yapılarını uygulamak için işaretçilere ihtiyacınız var
  • Bellek kullanımında etkin olmak için işaretçilere ihtiyacınız var
  • İşe gitmek için manuel bellek indeksleme gerekmez eğer doğrudan donanım kullanmıyorsunuz.

Dolayısıyla, referanslar.


32

Basit Cevap:

Bir yerden geçen her nesnenin derin bir kopyasını oluşturup yaparken bellek tüketimini
ve CPU süresini en aza indirgemek
.


Size katılıyorum, ancak bence bunlar arasında estetik veya OO tasarım motivasyonu da var.
Gustavo Cardoso

9
@Gustavo Cardoso: "Bazı estetik ya da OO tasarım motivasyonu". Hayır. Sadece bir optimizasyon.
S.Lott

6
@ S.Lott: Hayır, referans olarak geçmek OO terimlerinin anlamlıdır çünkü anlamsal olarak nesnelerin kopyalarını almak istemezsiniz. Nesneyi bir kopyasından ziyade geçmek istiyorsunuz . Değere göre geçiyorsanız, OO metaforunu bir parça kırar, çünkü daha yüksek bir düzeyde mantıklı olmayan tüm yerde üretilen tüm bu nesne klonlarına sahipsiniz.
intuited

@Gustavo: Sanırım aynı noktayı tartışıyoruz. OOP'un anlambiliminden bahsediyorsunuz ve OOP'un metaforuna kendime ek nedenler olarak bakıyorsunuz. Bana göre OOP yaratıcıları "bellek tüketimini en aza indirmeyi" ve "CPU zamanından tasarruf etmeyi" başardılar
Tim

14

C ++ 'da iki ana seçeneğiniz vardır: değere göre döndür veya işaretçi ile döndür. İlkine bakalım:

MyClass getNewObject() {
    MyClass newObj;
    return newObj;
}

Derleyicinizin geri dönüş değeri optimizasyonunu kullanacak kadar akıllı olmadığını varsayalım, burada olanlar şudur:

  • newObj geçici bir nesne olarak oluşturulur ve yerel yığına yerleştirilir.
  • NewObj'nin bir kopyası oluşturulur ve döndürülür.

Nesnenin bir kopyasını anlamsızca yaptık. Bu işlem zaman kaybıdır.

İşaretçi dönüşüne bakalım:

MyClass* getNewObject() {
    MyClass newObj = new MyClass();
    return newObj;
}

Gereksiz kopyayı ortadan kaldırdık, ancak şimdi başka bir sorun ortaya koyduk: Öbek üzerinde otomatik olarak yok edilmeyen bir nesne yarattık. Bununla kendimiz başa çıkmalıyız:

MyClass someObj = getNewObject();
delete someObj;

Bu şekilde tahsis edilen bir nesneyi silmekle kimin sorumlu olduğunu bilmek, sadece yorum veya kongre ile iletilebilecek bir şeydir. Kolayca hafıza sızıntılarına yol açar.

Bu iki sorunu çözmek için çok sayıda çözüm önerilmiştir - geri dönüş değeri optimizasyonu (derleyicinin, geri dönüş değerinde gereksiz kopya oluşturmayacak kadar akıllı olduğu), yönteme yapılan bir referansı iletme yeni bir tane oluşturmak yerine mevcut nesneyi), akıllı işaretçiler (sahiplik meselesi tartışmalı olacak şekilde).

Java / C # yaratıcıları, nesneyi her zaman referans alarak döndürmenin daha iyi bir çözüm olduğunu anladılar, özellikle de dil onu destekliyorsa. Dil toplama, çöp toplama gibi diğer birçok özelliğe bağlanır.


Değere göre dönüş yeterince kötü, ancak değere göre geçiş değeri nesnelere gelince daha da kötü, ve kaçınmaya çalıştıkları asıl sorun bence.
Mason Wheeler

Elbette geçerli bir puanınız var. Fakat OO @Mason'un işaret ettiği problemi değişimin nihai motivasyonu olarak tasarladı. Sadece referansı kullanmak istediğinizde referans ile değer arasındaki farkı korumanın bir anlamı yoktu.
Gustavo Cardoso

10

Diğer birçok cevaplar iyi bilgiye sahiptir. Sadece kısmen ele alınan klonlama hakkında önemli bir nokta eklemek istiyorum .

Referansları kullanmak akıllıdır. Bir şeyleri kopyalamak tehlikelidir.

Diğerlerinin dediği gibi, Java’da doğal bir “klon” yoktur. Bu sadece eksik bir özellik değil. Sen asla sadece ister istemez * kopyası (Sığ olsun veya derin) bir nesnenin her özellik istiyorum. Ya bu özellik bir veritabanı bağlantısı olsaydı? Bir insanı klonlayabileceğinden daha fazla bir veritabanı bağlantısını klonlayamazsın. Başlatma bir nedenden dolayı var.

Derin kopyalar kendi başlarına bir sorun - gerçekten ne kadar derine gidiyorsun? Statik olan herhangi bir şeyi ( Classnesneler dahil ) kesinlikle kopyalayamazsınız .

Dolayısıyla, doğal bir klonun olmadığı nedenlerden ötürü, kopya olarak geçen nesneler delilik yaratacaktır . Bir DB bağlantısını "klonlayabilseniz" bile - bunun kapalı olduğundan nasıl emin olabilirsiniz?


* Yorumlara bakın - Bu "asla" ifadesiyle, her özelliği klonlayan otomatik bir klonu kastediyorum . Java bir tane sağlamadı ve muhtemelen burada listelenen nedenlerden dolayı, kendi dilini yaratan bir dil kullanıcısı olarak sizin için iyi bir fikir değildir. Sadece geçici olmayan alanları klonlamak bir başlangıç ​​olacaktır, ancak o zaman bile transientuygun olanı tanımlama konusunda gayretli olmanız gerekir .


İyi itirazlardan , belirli şartlarda klonlamaya , asla ihtiyaç duyulmadığına dair ifadeye atlamakta zorluk çekiyorum . Ve tam bir kopyanın gerekli olduğu, ilgili statik fonksiyonların olmadığı, hiçbir IO ya da açık bağlantıların söz konusu olamadığı durumlar ile karşılaştım ... Klonlamanın risklerini anlıyorum ama battaniyeyi asla göremiyorum .
Inca,

2
@Inca - Beni yanlış anlıyor olabilirsin. Kasıtlı olarak uygulanan cloneiyidir. "Willy-nilly" ile, bütün özelliklerini düşünmeden kopyalamak kastedilerek - kasıtlı bir niyet olmadan. Java dili tasarımcıları, bu amaç için, kullanıcı tarafından oluşturulan bir uygulama gerektirerek zorladı clone.
Nicole

Değişmez nesnelere referanslar kullanmak akıllıdır. Date gibi değişkenler yapmak gibi basit değerler yapmak ve bunlara çoklu referanslar oluşturmak değildir.
kevin

@NickC: "Nilly willy yapmanın asıl nedeni" tehlikelidir, Java ve .net gibi dillerin / çerçevelerin, bir referansın değişebilir durumu, kimliği veya her ikisini de kapsamayacağını açıkça bildirmek için herhangi bir yolu bulunmamasıdır. Alan, değişken durumu içeren ancak kimliği içermeyen bir nesne başvurusu içeriyorsa, nesneyi klonlamak, durumu tutan nesnenin çoğaltılmasını ve alanda saklanan söz konusu kopyaya bir başvuru yapılmasını gerektirir. Başvuru kimliğe sahipse ancak değişken durum içermiyorsa, kopyadaki alan orijinal ile aynı nesneye başvurmalıdır.
supercat,

Derin kopya yönü önemli bir nokta. Nesneleri kopyalamak, özellikle de nesne grafiği değiştirilebilir nesneler içeriyorsa, diğer nesnelere referanslar içerdiğinde sorunludur.
Caleb

4

Nesnelere her zaman Java ile başvurulur. Asla kendi başlarına geçemezler.

Bir avantaj, bunun dili basitleştirmesidir. Bir C ++ nesnesi, bir üyeye erişmek için iki farklı işleç kullanma gereksinimi yaratarak bir değer veya başvuru olarak gösterilebilir: .ve ->. (Bunun birleştirilememesinin sebepleri vardır; örneğin akıllı işaretçiler referans olan değerlerdir ve bunları farklı tutmaları gerekir.) Yalnızca Java ihtiyacı vardır ..

Başka bir neden ise polimorfizmin değer değil referans olarak yapılması gerektiğidir; değere göre işlem gören bir nesne tam oradadır ve sabit bir türe sahiptir. Bunu C ++ 'da mahvetmek mümkün.

Ayrıca, Java varsayılan atamayı / kopyalamayı / herhangi bir şekilde değiştirebilir. C ++ 'da, az ya da çok derin bir kopya, Java'da ise basit bir işaretçi ataması / kopyala / her neyse, .clone()kopyalamanız gerekiyorsa böyle.


Bazen '(* object) ->' kullandığınızda çok çirkinleşiyor
Gustavo Cardoso

1
C ++ 'ın işaretçiler, referanslar ve değerler arasında ayrım yaptığını belirtmek önemlidir. SomeClass * bir nesneye işaretçidir. SomeClass & bir nesneye referanstır. SomeClass bir değer türüdür.
Ant

Ben zaten ilk soruyu @Rober'a sordum, ancak burada da yapacağım: * ile & ++ arasındaki fark sadece düşük seviyeli bir teknik şey değil mi? Onlar, yüksek düzeyde, anlamsal olarak onlar aynı mıdır?
Gustavo Cardoso

3
@Gustavo Cardoso: Fark anlamlıdır; Düşük teknik seviyede genellikle aynıdırlar. Bir işaretçi bir nesneyi gösterir veya NULL (tanımlanmış bir hatalı değer). Aksi takdirde const, değeri diğer nesnelere işaret edecek şekilde değiştirilebilir. Başvuru bir nesne için başka bir addır, NULL olamaz ve tekrar edilemez. Genellikle basit işaretçiler kullanımıyla uygulanır, ancak bu bir uygulama detayıdır.
David Thornley

"Polimorfizm referans olarak yapılmalıdır" için +1. Bu, çoğu cevabın göz ardı ettiği inanılmaz derecede önemli bir detay.
Doval,

4

Referansla iletilen C # nesneleriyle ilgili ilk ifadeniz doğru değil. C # 'da, nesneler referans türleridir, ancak varsayılan olarak, değer türleri gibi değere göre iletilirler. Bir referans tipi söz konusu olduğunda, bir by-value yöntemi parametresi olarak kopyalanan "değer" referansın kendisidir, bu nedenle bir yöntem içindeki özelliklerde yapılan değişiklikler yöntem kapsamı dışına yansıtılır.

Bununla birlikte, parametre değişkenini bir yöntemin içine yeniden atadıysanız, bu değişikliğin yöntem kapsamı dışına yansıtılmadığını göreceksiniz. Buna karşılık, refanahtar kelimeyi kullanarak referans olarak bir parametreyi gerçekten geçirirseniz , bu davranış beklendiği gibi çalışır.


3

Hızlı cevap

Java ve benzer dil tasarımcıları "her şey bir nesnedir" konseptini uygulamak istedi. Ve verileri referans olarak iletmek çok hızlıdır ve fazla bellek tüketmez.

Ek genişletilmiş sıkıcı yorum

Sonunda, bu diller nesne referansları kullanır (Java, Delphi, C #, VB.NET, Vala, Scala, PHP), gerçek şu ki nesne referansları gizlenmiş nesnelere işaretçilerdir. Boş değer, bellek tahsisi, bir nesnenin tüm verilerini kopyalamadan referansın kopyalanması, hepsi düz işaretçiler değil, nesne işaretçilerdir !!!

Nesne Pascal'da (Delphi değil), anc C ++ (Java değil, C # değil), bir nesne, bir işaretçi kullanımı ("nesne başvurusu" olmadan "kullanılarak, statik ayrılmış bir değişken olarak ve ayrıca dinamik bir ayrılmış değişkenle bildirilebilir. şeker sözdizimi "). Her durumda, belirli bir sözdizimi kullanılır ve Java "ve arkadaşlarınızda" olduğu gibi kafanın karışması için bir yol yoktur. Bu dillerde, bir nesne hem değer olarak hem de referans olarak geçirilebilir.

Programcı, bir işaretçi sözdiziminin ne zaman gerekli olduğunu ve ne zaman gerekmediğini bilir, ancak Java ve benzer dillerde, bu kafa karıştırıcıdır.

Java mevcut veya ana akım haline gelmeden önce, pek çok programcı C ++ 'da işaretçiler olmadan OO öğrendi, gerektiğinde değere ya da referansa göre geçti. Öğrenmeden iş uygulamalarına geçildiğinde, genellikle nesne işaretçileri kullanırlar. QT kütüphanesi buna iyi bir örnektir.

Java'yı öğrendiğimde her şeyi bir nesne konsepti olarak takip etmeye çalıştım, ancak kodlamada kafam karıştı. Sonunda, "Tamam, dinamik olarak ayrılmış bir nesnenin sözdizimine sahip bir işaretçiyle dinamik olarak tahsis edilen nesneler" dedim ve tekrar kodlamakta zorlanmadım.


3

Java ve C # sizden düşük seviyeli bellek üzerinde kontrolü ele alıyor. Yarattığınız nesnelerin bulunduğu “yığın” kendi hayatını yaşar; örneğin, çöp toplayıcı ne zaman tercih ederse nesneleri toplar.

Programınız ve bu "yığın" arasında ayrı bir aktarım katmanı olduğundan, bir nesneye, değere ve işaretçiyle (C ++ 'da olduğu gibi) başvurmanın iki yolu ayırt edilemez hale gelir : daima nesnelere "işaretçiyle" göre yığında bir yerde. Bu nedenle bu tasarım yaklaşımı, varsayılan ödev anlamını referans olarak kullanır. Java, C #, Ruby ve diğerleri.

Yukarıdakiler yalnızca zorunlu dillerle ilgilidir. Bellekte üzerinde kontrol yukarıda belirtilen dillerde zamanında geçirilen, ama dil tasarımı da diyor "Hey, ama aslında orada olduğunu olduğunu bellek ve orada olan nesneler ve bunlar do bellek işgal". İşlevsel diller, “hafıza” kavramını tanımlarının dışında tutularak daha da soyutlamaktadır. Bu nedenle referans referansının, düşük-seviye belleği kontrol etmediğiniz tüm diller için mutlaka geçerli olmaması gerekir.


2

Birkaç neden düşünebilirim:

  • İlkel türlerin kopyalanması önemsizdir, genellikle tek bir makine komutuna çevrilir.

  • Nesnelerin kopyalanması önemsiz değildir, nesne, kendileri olan üyeler içerebilir. Nesnelerin kopyalanması CPU zamanı ve hafızasında pahalıdır. Bağlama bağlı olarak bir nesneyi kopyalamanın birçok yolu bile vardır.

  • Nesneleri referansa göre geçirmek ucuzdur ve nesne bilgilerini nesnenin birden fazla istemcisi arasında paylaşmak / güncellemek istediğinizde de kullanışlı olur.

  • Karmaşık veri yapıları (özellikle özyinelemeli olanlar) işaretçiler gerektirir. Nesneleri referans alarak geçirmek, işaretçilerden geçmek için daha güvenli bir yoldur.


1

Çünkü aksi takdirde, işlev otomatik olarak kendisine iletilen her tür nesnenin (açıkça derin) bir kopyasını oluşturabilmelidir. Ve genellikle bunu yapmayı tahmin edemez. Bu nedenle, tüm nesneleriniz / sınıflarınız için kopyalama / klonlama yöntemi uygulamasını tanımlamanız gerekir.


Sadece sığ bir kopya yapabilir ve gerçek değerleri ve işaretçileri diğer nesnelere tutabilir mi?
Gustavo Cardoso

#Gustavo Cardoso, bundan sonra diğer nesneleri değiştirebilirsin, referans olarak geçilmeyen bir nesneden ne bekleyeceksin?
David,

0

Çünkü Java daha iyi bir C ++ olarak tasarlandı ve C # daha iyi bir Java olarak tasarlandı ve bu dillerin geliştiricileri, nesnelerin değer türü olduğu temelde kırılmış C ++ nesne modelinden bıktı.

Nesne yönelimli programlamanın üç temel ilkesinden ikisi miras ve polimorfizmdir ve nesneleri referans türleri yerine değer türleri olarak ele almak ikisine de zarar vermektedir. Bir nesneyi parametre olarak bir işleve ilettiğinizde, derleyicinin kaç bayt geçeceğini bilmesi gerekir. Nesneniz bir referans türü olduğunda, cevap basittir: bir işaretçinin boyutu, tüm nesneler için aynıdır. Ancak nesneniz bir değer türü olduğunda, değerin gerçek boyutunu geçmek zorundadır. Türetilmiş bir sınıf yeni alanlar ekleyebildiğinden, bu sizof (türetilmiş)! = Sizeof (base) anlamına gelir ve polimorfizm pencereden dışarı çıkar.

İşte sorunu gösteren önemsiz bir C ++ programı:

#include <iostream> 
class Parent 
{ 
public: 
   int a;
   int b;
   int c;
   Parent(int ia, int ib, int ic) { 
      a = ia; b = ib; c = ic;
   };
   virtual void doSomething(void) { 
      std::cout << "Parent doSomething" << std::endl;
   }
};

class Child : public Parent {
public:
   int d;
   int e;
   Child(int id, int ie) : Parent(1,2,3) { 
      d = id; e = ie;
   };
   virtual void doSomething(void) {
      std::cout << "Child doSomething : D = " << d << std::endl;
   }
};

void foo(Parent a) {
   a.doSomething();
}

int main(void)
{
   Child c(4, 5);
   foo(c);
   return 0;
}

Bu programın çıktısı herhangi bir aklı OO dilinde eşdeğer bir program için ne olacağını değil çünkü türetilmiş bir nesneyi değere göre bir temel nesneyi bekleyen bir işleve geçiremezsiniz, böylece derleyici gizli bir kopya kurucu oluşturur ve geçer Child nesnesinin Üst kısmının bir kopyası, Yaptığınız gibi Child nesnesini iletmek yerine. Bunun gibi gizli anlamsal yaklaşımlar, nesnelerin değerine göre C ++ 'dan kaçınılmasının önlenmesinin nedenidir ve hemen hemen her OO dilinde hiç mümkün değildir.


Çok iyi bir nokta. Ancak, geri dönüş problemlerine odaklandım, çünkü etraflarında çalışmak oldukça çaba gösteriyor; Bu program, bir tek ve ek işareti ile sabitlenebilir: void foo (Parent & a)
Ant

OO gerçekten işaretçiler olmadan çalışmıyor
Gustavo Cardoso

-1.000000000000
P

5
Java'nın değere göre değer taşıdığını hatırlamak önemlidir (nesne referansları değere göre iletilirken nesne referanslarını değere göre iletir).
Nicole

3
@Pavel Shved - "iki tane bir taneden iyidir!" Veya başka bir deyişle, kendinizi asmak için daha fazla ip.
Nicole

0

Çünkü aksi halde polimorfizm olmazdı.

OO Programlama'da, birinden daha büyük bir Derivedsınıf oluşturabilir Baseve daha sonra bir Basetanesini bekleyen fonksiyonlara geçirebilirsiniz . Oldukça önemsiz ha?

Bir fonksiyonun argümanının büyüklüğü sabittir ve derleme zamanında belirlenir. İstediğiniz her şeyi iddia edebilirsiniz, çalıştırılabilir kod bu şekildedir ve dillerin bir noktada veya başka bir yerde yürütülmesi gerekir (yalnızca yorumlanmış diller bununla sınırlı değildir ...)

Şimdi, bilgisayarda iyi tanımlanmış bir veri parçası var: genellikle bir veya iki "kelime" olarak ifade edilen bir bellek hücresinin adresi. Programlama dillerinde işaretçiler veya referanslar olarak görülebilir.

Dolayısıyla, keyfi uzunluktaki nesneleri iletmek için yapılacak en basit şey, bu nesneye bir işaretçi / başvuru iletmektir.

Bu, OO Programlamanın teknik bir sınırlamasıdır.

Ancak, büyük türler için, kopyalamayı önlemek için genellikle referansları geçmeyi tercih ettiğiniz için, bu genellikle büyük bir darbe sayılmaz :)

Java veya C # 'da, bir nesneyi bir yönteme geçirirken, nesnenin yöntem tarafından değiştirilip değiştirilmeyeceği konusunda hiçbir fikriniz olmasa da, önemli bir sonuç vardır. Hata ayıklama / paralelleştirmeyi zorlaştırır ve bu İşlevsel Diller ve Saydamlık Referansının ele almaya çalıştığı -> kopyalamanın fena olmamasıdır (mantıklı olduğunda).


-1

Cevap, adında (hemen hemen her neyse). Bir referans (bir adres gibi) sadece başka bir şeyi ifade eder, değer başka bir şeyin başka bir kopyasıdır. Birisinin muhtemelen aşağıdaki etkilerden bahsettiğinden eminim, ancak birisinin uygun olmayan ve diğerinin uygun olmadığı durumlar olacaktır (Hafıza güvenliği - Hafıza Verimliliği). Her şey hafızayı, hafızayı, hafızayı yönetmekle ilgili… MEMORY! : D


-2

Tamam, bu yüzden tam olarak neden nesnelerin referans türü olduğunu ya da referanstan geçildiğini söylemiyorum ama size bunun neden uzun vadede çok iyi bir fikir olduğuna dair bir örnek verebilirim.

Yanılmıyorsam, bir sınıfı C ++ 'da miras aldığınızda, o sınıfın tüm yöntemleri ve özellikleri fiziksel olarak alt sınıfa kopyalanır. Bu sınıfın içeriğini tekrar çocuk sınıfına yazmak gibi bir şey olur.

Bu, çocuk sınıfınızdaki verilerin toplam boyutunun, ana sınıftaki ve türetilmiş sınıftaki öğelerin bir birleşimi olduğu anlamına gelir.

EG: #include

class Top 
{   
    int arrTop[20] = {1,2,3,4,5,6,7,8,9,9,8,7,6,5,4,3,2,1};
};  

class Middle : Top 
{   
    int arrMiddle[20] = {1,2,3,4,5,6,7,8,9,9,8,7,6,5,4,3,2,1};
};  

class Bottom : Middle
{   
    int arrBottom[20] = {1,2,3,4,5,6,7,8,9,9,8,7,6,5,4,3,2,1};
};  

int main()
{   
    using namespace std;

    int arr[20];
    cout << "Size of array of 20 ints: " << sizeof(arr) << endl;

    Top top;
    Middle middle;
    Bottom bottom;

    cout << "Size of Top Class: " << sizeof(top) << endl;
    cout << "Size of middle Class: " << sizeof(middle) << endl;
    cout << "Size of bottom Class: " << sizeof(bottom) << endl;

}   

Hangisi size gösterecekti:

Size of array of 20 ints: 80
Size of Top Class: 80
Size of middle Class: 160
Size of bottom Class: 240

Bunun anlamı, birkaç sınıftan oluşan büyük bir hiyerarşiniz varsa, burada belirtilen nesnenin toplam boyutunun, bu sınıfların hepsinin birleşimi olacağı anlamına gelir. Açıkçası, bu nesneler çoğu durumda oldukça büyük olacaktır.

Çözüm, öbek üzerinde oluşturmak ve işaretçiler kullanmak olduğuna inanıyorum. Bunun anlamı, birkaç ebeveyne sahip olan sınıf nesnelerinin boyutunun bir anlamda yönetilebilir olmasıdır.

Bu nedenle referansları kullanmak, bunu yapmak için daha çok tercih edilen bir yöntem olacaktır.


1
Bu, 13 önceki
cevapta
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.