Bağlantılı listeler düğümleri düğümlerin içinde depolamak yerine neden işaretçiler kullanıyor?


121

Daha önce Java'da yoğun olarak bağlantılı listelerle çalıştım, ancak C ++ konusunda çok yeniyim. Bana bir projede verilen bu düğüm sınıfını kullanıyordum gayet iyi

class Node
{
  public:
   Node(int data);

   int m_data;
   Node *m_next;
};

ama çok iyi cevaplanmamış bir sorum vardı. Neden kullanmak gerekli

Node *m_next;

yerine listedeki sonraki düğümü işaret etmek için

Node m_next;

İşaretçi sürümünü kullanmanın daha iyi olduğunu anlıyorum; Gerçekleri tartışmayacağım ama neden daha iyi olduğunu bilmiyorum. İşaretçinin bellek ayırma için nasıl daha iyi olduğuna dair o kadar net olmayan bir cevabım var ve buradaki herhangi birinin bunu daha iyi anlamama yardım edip edemeyeceğini merak ediyordum.


14
@ Özür dilerim? Neden her şeyin işaretçi olduğu bir dilin bağlantılı listeleri yok?
Angew artık SO

41
C ve C ++ 'nın, nesne işaretçileri ve referanslar açısından Java'dan ne kadar farklı olduğuna dikkat etmek önemlidir. Node m_nextbir düğüme referans değil, tüm Nodekendisi için depolamadır .
Brian Cain

41
@self Java'nın açıkça kullanmadığınız işaretçileri vardır.
m0meni

27
Tüm yol aşağı kaplumbağalar olduğunu değil bir seçenek. Delilik bir yerde bitmeli.
WhozCraig

26
Lütfen Java hakkında bildiğiniz her şeyi unutun . C ++ ve Java, belleği temelde farklı şekillerde kullanır. Kitap önerileri için bu soruya bakın , birini seçin ve okuyun. Hepimize büyük bir iyilik yapacaksın.
Rob K

Yanıtlar:


218

Bu sadece daha iyi değil, mümkün olan tek yol bu.

Kendi içinde bir Node nesne saklarsanız ne olur sizeof(Node)? Bu olacaktır sizeof(int) + sizeof(Node)eşit olacağını, sizeof(int) + (sizeof(int) + sizeof(Node))eşit olacağını, sizeof(int) + (sizeof(int) + (sizeof(int) + sizeof(Node)))sonsuza vb.

Böyle bir nesne var olamaz. Bu var imkansız .


25
* Tembel değerlendirilmedikçe. Sınırsız listeler mümkündür, ancak katı bir değerlendirmeyle mümkün değildir.
Carcigenicate

55
@Carcigenicate Bu, Node nesnesinde bazı işlevlerin değerlendirilmesi / yürütülmesi ile ilgili değildir - bu, herhangi bir değerlendirme yapılmadan önce derleme zamanında belirlenmesi gereken Node'un her örneğinin bellek düzeniyle ilgilidir.
Peteris

6
@DavidK Bunu yapmak mantıksal olarak imkansız. Sen lüzum burada bir işaretçi (gerçekten iyi bir indirection) - senden gizleyebilirsiniz emin dil, ancak bu çevrede sonunda, olamaz.
Voo

2
@David kafam karıştı. Önce mantıksal olarak imkansız olduğuna katılıyorsunuz, ama sonra onu düşünmek mi istiyorsunuz? C veya C ++ 'dan herhangi bir şeyi kaldırın - hayal edebileceğiniz herhangi bir dilde görebildiğim kadarıyla bu imkansız . Bu yapı, tanım gereği sonsuz bir özyinedir ve bir miktar dolaylılık olmadan bunu kıramayız.
Voo

13
@benjamin Aslında, Haskell'in yaratılış sırasında thunk'ları tahsis ettiğini ve dolayısıyla bu işe yaradığını çünkü bu thunks bize ihtiyacımız olan indirimi verdiğini belirttim (çünkü başka türlü birinin bunu gündeme getireceğini biliyordum - pek yardımcı olmadı). Bu, fazladan veri gizlenmiş bir işaretçiden başka bir şey değil ...
Voo

178

Java'da

Node m_node

başka bir düğüme bir işaretçi depolar. Bununla ilgili seçeneğin yok. C ++ ile

Node *m_node

aynı anlama gelir. Aradaki fark, C ++ 'da bir işaretçinin aksine nesneyi gerçekten depolayabilmenizdir. Bu yüzden bir işaretçi istediğini söylemelisin. C ++ 'da:

Node m_node

düğümü burada depolamak anlamına gelir (ve bu açıkça bir liste için çalışmaz - sonunda yinelemeli olarak tanımlanmış bir yapıya sahip olursunuz).


2
@SalmanA Bunu zaten biliyordum. Sadece neden bir işaretçi olmadan işe yaramayacağını bilmek istedim ki bu kabul edilen yanıtın çok daha iyi açıkladığı şeydi.
m0meni

3
@ AR7 İki farklı yaklaşımın altında ikisi de aynı açıklamayı yapıyorlar. Bunu "normal" bir değişken olarak ilan ettiyseniz, bir kurucu ilk kez çağrıldığında, bunu yeni bir örneğe somutlaştıracaktır. Ancak, onu başlatmayı bitirmeden önce - birincinin kurucusu bitmeden önce - üyenin Nodekendi kurucusu çağrılır ve bu da başka bir yeni örneği başlatır ... ve sonsuz sözde özyineleme elde edersiniz. O değil gerçekten bir performans sorunu olduğu gibi, bu kadar tamamen sıkı ve edebi açıdan bir boyut sorunu.
Panzercrisis

Ama gerçekten istediğiniz tek şey listede hangisinin bir sonraki olduğuna işaret etmenin bir yolu, Nodeaslında ilkinin içinde olan değil Node. Böylece, Java'nın nesneleri ilkellerin aksine işleyiş şekli olan bir işaretçi yaratırsınız. Bir yöntemi çağırdığınızda veya bir değişken oluşturduğunuzda, Java nesnenin bir kopyasını veya hatta nesnenin kendisini saklamaz; Temelde etrafına biraz çocuk eldiveni sarılı bir işaretçi olan bir nesneye bir referans depolar. Her iki cevabın da aslında söylediği şey bu.
Panzercrisis

bu bir boyut veya hız sorunu değil - bu imkansız bir sorun. Dahil edilen Node nesnesi, bir Node nesnesi içeren bir Node nesnesi içerir ... Aslında onu derlemek imkansızdır
pm100

3
@Panzercrisis İkisinin de aynı açıklamayı yaptıklarının farkındayım. Bununla birlikte, bu yaklaşım bana o kadar yardımcı olmadı çünkü zaten anladığım şeye odaklandı: C ++ 'da işaretçilerin nasıl çalıştığı ve Java'da işaretçilerin nasıl ele alındığı. Kabul edilen cevap , boyut hesaplanamadığı için neden bir işaretçi kullanmamanın imkansız olduğuna özellikle değindi . Öte yandan, bu onu daha belirsiz bir şekilde "yinelemeli olarak tanımlanmış bir yapı" olarak bıraktı. Not: Az önce yazdığınız açıklamanız onu her ikisinden de daha iyi açıklıyor: D.
m0meni

38

C ++, Java değildir. Yazarken

Node m_next;

Java'da yazmakla aynı şey

Node* m_next;

C ++ 'da. Java'da işaretçi örtüktür, C ++ 'da belirgindir. Eğer yazarsan

Node m_next;

C ++ 'da, Nodetanımladığınız nesnenin içine bir örnek koyarsınız . Her zaman oradadır ve ihmal edilemez, tahsis newedilemez ve kaldırılamaz. Bu etkiyi Java'da elde etmek imkansızdır ve Java'nın aynı sözdizimi ile yaptığından tamamen farklıdır.


1
Java'da benzer bir şey elde etmek için SuperNode Düğümü genişletirse muhtemelen "genişler" olacaktır, Süper Düğümler Düğümün tüm Niteliklerini içerir ve tüm ek alanı ayırmak zorundadır. Yani Java'da "Düğüm, Düğümü genişletir" seçeneğini yapamazsınız
Falco

@Falco Doğru, kalıtım, temel sınıfların yerinde dahil edilmesinin bir biçimidir. Bununla birlikte, Java çoklu kalıtıma izin vermediğinden (C ++ 'dan farklı olarak), miras yoluyla yalnızca önceden var olan başka bir sınıfın bir örneğini çekebilirsiniz. Bu nedenle, mirasın, üyelerin yerinde dahil edilmesinin bir ikamesi olduğunu düşünmüyorum.
cmaster

27

Bir işaretçi kullanıyorsunuz, aksi takdirde kodunuz:

class Node
{
   //etc
   Node m_next; //non-pointer
};

... olur değil derleyici boyutunu hesaplamak olamaz gibi derlemek Node. Bunun nedeni, kendisine bağlı olmasıdır - bu, derleyicinin ne kadar bellek tüketeceğine karar veremeyeceği anlamına gelir.


5
Daha da kötüsü, geçerli bir boyut yok: k == sizeof(Node)Muhafazalar ve türünüzde veri varsa, bunu sizeof(Node) = k + sizeof(Data) = sizeof(Node) + sizeof(Data)ve sonra da tutması gerekir sizeof(Node) > sizeof(Node).
bitmask

4
@bitmask gerçek sayılarda geçerli bir boyut yok . Transinfinite izin verirseniz aleph_0çalışır. (Sadece aşırı
bilgiççe

2
@k_g C / C ++ standardı, dönüş değerinin sizeofişaretsiz bir integral türü olmasını zorunlu kılar , bu nedenle, sonsuz ve hatta gerçek boyutlar umudu vardır. (daha bilgiççe davranmak!: p)
Thomas

@Thomas: Hatta Doğal Sayıların bile gittiğini söyleyebiliriz. (Pedantik tepenin üzerinden geçmek: p)
bit maskesi

1
Aslında, Nodebu pasajın sonundan önce bile tanımlanmamıştır, bu yüzden içeride gerçekten kullanamazsınız. Henüz bildirilmemiş bir sınıfa işaretçilerin dolaylı olarak bildirilmesine izin vermek, bu tür yapıları her zaman açıkça işaretçi atmaya gerek kalmadan mümkün kılmak için dil tarafından izin verilen küçük bir aldatmacadır.
osa

13

İkincisi ( Node m_next) düğümü içermelidir . Onu işaret etmez. Ve böylece öğeler arasında bağlantı olmayacaktı.


3
Daha kötüsü, bir nesnenin aynı türden bir şey içermesi mantıksal olarak imkansızdır.
Mike Seymour

Hala teknik olarak bağlanma olmaz mıydı, çünkü bir düğüm içeren bir düğüm içeren bir düğüm vb.
m0meni

9
@ AR7: Hayır, kapsama, kelimenin tam anlamıyla nesnenin içinde olduğu, ona bağlı olmadığı anlamına gelir.
Mike Seymour

9

Tanımladığınız yaklaşım yalnızca C ++ ile değil, aynı zamanda (çoğunlukla) alt küme dili C ile de uyumludur . C tarzı bir bağlantılı liste geliştirmeyi öğrenmek, kendinizi düşük düzeyli programlama tekniklerine (manuel bellek yönetimi gibi) tanıtmanın iyi bir yoludur, ancak genellikle modern C ++ geliştirme için en iyi uygulama değildir .

Aşağıda, C ++ 'da bir öğe listesinin nasıl yönetileceğine dair dört varyasyon uyguladım.

  1. raw_pointer_demosizinkiyle aynı yaklaşımı kullanır - ham işaretçilerin kullanımıyla gerekli olan manuel bellek yönetimi. Burada C ++ kullanımı yalnızca sözdizimsel şeker içindir ve kullanılan yaklaşım, aksi takdirde C diliyle uyumludur.
  2. Gelen shared_pointer_demoliste yönetimi hala elle yapılır, ancak hafıza yönetimi otomatik (ham işaretçileri kullanmaz). Bu, muhtemelen Java ile yaşadıklarınıza çok benzer.
  3. std_list_demostandart kitaplık listkonteynerini kullanır . Bu, kendi kütüphanenizi sürmek yerine mevcut kitaplıklara güvenirseniz işlerin ne kadar kolaylaştığını gösterir.
  4. std_vector_demostandart kitaplık vectorkonteynerini kullanır . Bu, liste depolamasını tek bir bitişik bellek ayırmasında yönetir. Başka bir deyişle, tek tek öğelere ilişkin işaretler yoktur. Oldukça aşırı bazı durumlar için, bu önemli ölçüde verimsiz hale gelebilir. Ancak tipik durumlarda, C ++ 'da liste yönetimi için önerilen en iyi uygulama budur .

Not: Bunların hepsinden sadece, raw_pointer_demohafızanın "sızmasını" önlemek için listenin açıkça imha edilmesini gerektirir. Diğer üç yöntem , kapsayıcı kapsam dışına çıktığında (işlevin sonunda) listeyi ve içeriğini otomatik olarak yok eder. Buradaki nokta şu: C ++, bu bakımdan çok "Java benzeri" olabilir - ancak yalnızca, programınızı emrinizde olan üst düzey araçları kullanarak geliştirmeyi seçerseniz.


/*BINFMTCXX: -Wall -Werror -std=c++11
*/

#include <iostream>
#include <algorithm>
#include <string>
#include <list>
#include <vector>
#include <memory>
using std::cerr;

/** Brief   Create a list, show it, then destroy it */
void raw_pointer_demo()
{
    cerr << "\n" << "raw_pointer_demo()..." << "\n";

    struct Node
    {
        Node(int data, Node *next) : data(data), next(next) {}
        int data;
        Node *next;
    };

    Node * items = 0;
    items = new Node(1,items);
    items = new Node(7,items);
    items = new Node(3,items);
    items = new Node(9,items);

    for (Node *i = items; i != 0; i = i->next)
        cerr << (i==items?"":", ") << i->data;
    cerr << "\n";

    // Erase the entire list
    while (items) {
        Node *temp = items;
        items = items->next;
        delete temp;
    }
}

raw_pointer_demo()...
9, 3, 7, 1

/** Brief   Create a list, show it, then destroy it */
void shared_pointer_demo()
{
    cerr << "\n" << "shared_pointer_demo()..." << "\n";

    struct Node; // Forward declaration of 'Node' required for typedef
    typedef std::shared_ptr<Node> Node_reference;

    struct Node
    {
        Node(int data, std::shared_ptr<Node> next ) : data(data), next(next) {}
        int data;
        Node_reference next;
    };

    Node_reference items = 0;
    items.reset( new Node(1,items) );
    items.reset( new Node(7,items) );
    items.reset( new Node(3,items) );
    items.reset( new Node(9,items) );

    for (Node_reference i = items; i != 0; i = i->next)
        cerr << (i==items?"":", ") << i->data;
    cerr<<"\n";

    // Erase the entire list
    while (items)
        items = items->next;
}

shared_pointer_demo()...
9, 3, 7, 1

/** Brief   Show the contents of a standard container */
template< typename C >
void show(std::string const & msg, C const & container)
{
    cerr << msg;
    bool first = true;
    for ( int i : container )
        cerr << (first?" ":", ") << i, first = false;
    cerr<<"\n";
}

/** Brief  Create a list, manipulate it, then destroy it */
void std_list_demo()
{
    cerr << "\n" << "std_list_demo()..." << "\n";

    // Initial list of integers
    std::list<int> items = { 9, 3, 7, 1 };
    show( "A: ", items );

    // Insert '8' before '3'
    items.insert(std::find( items.begin(), items.end(), 3), 8);
    show("B: ", items);

    // Sort the list
    items.sort();
    show( "C: ", items);

    // Erase '7'
    items.erase(std::find(items.begin(), items.end(), 7));
    show("D: ", items);

    // Erase the entire list
    items.clear();
    show("E: ", items);
}

std_list_demo()...
A:  9, 3, 7, 1
B:  9, 8, 3, 7, 1
C:  1, 3, 7, 8, 9
D:  1, 3, 8, 9
E:

/** brief  Create a list, manipulate it, then destroy it */
void std_vector_demo()
{
    cerr << "\n" << "std_vector_demo()..." << "\n";

    // Initial list of integers
    std::vector<int> items = { 9, 3, 7, 1 };
    show( "A: ", items );

    // Insert '8' before '3'
    items.insert(std::find(items.begin(), items.end(), 3), 8);
    show( "B: ", items );

    // Sort the list
    sort(items.begin(), items.end());
    show("C: ", items);

    // Erase '7'
    items.erase( std::find( items.begin(), items.end(), 7 ) );
    show("D: ", items);

    // Erase the entire list
    items.clear();
    show("E: ", items);
}

std_vector_demo()...
A:  9, 3, 7, 1
B:  9, 8, 3, 7, 1
C:  1, 3, 7, 8, 9
D:  1, 3, 8, 9
E:

int main()
{
    raw_pointer_demo();
    shared_pointer_demo();
    std_list_demo();
    std_vector_demo();
}

Yukarıdaki Node_referencebildirim, Java ve C ++ arasındaki en ilginç dil seviyesi farklılıklarından birini ele almaktadır. Java'da, türden bir nesnenin Nodebildirilmesi örtük olarak ayrı olarak ayrılmış bir nesneye bir başvuru kullanır. C ++ 'da, başvuru (işaretçi) ve doğrudan (yığın) ayırma seçeneklerine sahipsiniz - bu nedenle, ayrımı açıkça ele almanız gerekir. Çoğu durumda, liste öğeleri için olmasa da doğrudan ayırmayı kullanırsınız.
Brent Bradburn

Neden std :: deque olasılığını önermediğimi bilmiyorum .
Brent Bradburn

8

genel bakış

C ++ 'da nesneleri referans vermenin ve tahsis etmenin 2 yolu vardır, Java'da ise sadece bir yol vardır.

Bunu açıklamak için, aşağıdaki diyagramlar nesnelerin bellekte nasıl saklandığını göstermektedir.

1.1 C ++ İşaretçi olmayan öğeler

class AddressClass
{
  public:
    int      Code;
    char[50] Street;
    char[10] Number;
    char[50] POBox;
    char[50] City;
    char[50] State;
    char[50] Country;
};

class CustomerClass
{
  public:
    int          Code;
    char[50]     FirstName;
    char[50]     LastName;
    // "Address" IS NOT A pointer !!!
    AddressClass Address;
};

int main(...)
{
   CustomerClass MyCustomer();
     MyCustomer.Code = 1;
     strcpy(MyCustomer.FirstName, "John");
     strcpy(MyCustomer.LastName, "Doe");
     MyCustomer.Address.Code = 2;
     strcpy(MyCustomer.Address.Street, "Blue River");
     strcpy(MyCustomer.Address.Number, "2231 A");

   return 0;
} // int main (...)

.......................................
..+---------------------------------+..
..|          AddressClass           |..
..+---------------------------------+..
..| [+] int:      Code              |..
..| [+] char[50]: Street            |..
..| [+] char[10]: Number            |..
..| [+] char[50]: POBox             |..
..| [+] char[50]: City              |..
..| [+] char[50]: State             |..
..| [+] char[50]: Country           |..
..+---------------------------------+..
.......................................
..+---------------------------------+..
..|          CustomerClass          |..
..+---------------------------------+..
..| [+] int:      Code              |..
..| [+] char[50]: FirstName         |..
..| [+] char[50]: LastName          |..
..+---------------------------------+..
..| [+] AddressClass: Address       |..
..| +-----------------------------+ |..
..| | [+] int:      Code          | |..
..| | [+] char[50]: Street        | |..
..| | [+] char[10]: Number        | |..
..| | [+] char[50]: POBox         | |..
..| | [+] char[50]: City          | |..
..| | [+] char[50]: State         | |..
..| | [+] char[50]: Country       | |..
..| +-----------------------------+ |..
..+---------------------------------+..
.......................................

Uyarı : Bu örnekte kullanılan C ++ sözdizimi, Java'daki sözdizimine benzer. Ancak bellek tahsisi farklıdır.

1.2 İşaretçiler kullanan C ++ Öğeler

class AddressClass
{
  public:
    int      Code;
    char[50] Street;
    char[10] Number;
    char[50] POBox;
    char[50] City;
    char[50] State;
    char[50] Country;
};

class CustomerClass
{
  public:
    int           Code;
    char[50]      FirstName;
    char[50]      LastName;
    // "Address" IS A pointer !!!
    AddressClass* Address;
};

.......................................
..+-----------------------------+......
..|        AddressClass         +<--+..
..+-----------------------------+...|..
..| [+] int:      Code          |...|..
..| [+] char[50]: Street        |...|..
..| [+] char[10]: Number        |...|..
..| [+] char[50]: POBox         |...|..
..| [+] char[50]: City          |...|..
..| [+] char[50]: State         |...|..
..| [+] char[50]: Country       |...|..
..+-----------------------------+...|..
....................................|..
..+-----------------------------+...|..
..|         CustomerClass       |...|..
..+-----------------------------+...|..
..| [+] int:      Code          |...|..
..| [+] char[50]: FirstName     |...|..
..| [+] char[50]: LastName      |...|..
..| [+] AddressClass*: Address  +---+..
..+-----------------------------+......
.......................................

int main(...)
{
   CustomerClass* MyCustomer = new CustomerClass();
     MyCustomer->Code = 1;
     strcpy(MyCustomer->FirstName, "John");
     strcpy(MyCustomer->LastName, "Doe");

     AddressClass* MyCustomer->Address = new AddressClass();
     MyCustomer->Address->Code = 2;
     strcpy(MyCustomer->Address->Street, "Blue River");
     strcpy(MyCustomer->Address->Number, "2231 A");

     free MyCustomer->Address();
     free MyCustomer();

   return 0;
} // int main (...)

Her iki yol arasındaki farkı kontrol ederseniz, ilk teknikte adres öğesinin müşteri içinde tahsis edildiğini, ikinci yöntemde ise her adresi açıkça oluşturmanız gerektiğini göreceksiniz.

Uyarı: Java, bu ikinci teknik gibi nesneleri bellekte ayırır, ancak sözdizimi ilk yol gibidir ve bu, yeni gelenler için "C ++" için kafa karıştırıcı olabilir.

uygulama

Dolayısıyla liste örneğiniz aşağıdaki örneğe benzer olabilir.

class Node
{
  public:
   Node(int data);

   int m_data;
   Node *m_next;
};

.......................................
..+-----------------------------+......
..|            Node             |......
..+-----------------------------+......
..| [+] int:           m_data   |......
..| [+] Node*:         m_next   +---+..
..+-----------------------------+...|..
....................................|..
..+-----------------------------+...|..
..|            Node             +<--+..
..+-----------------------------+......
..| [+] int:           m_data   |......
..| [+] Node*:         m_next   +---+..
..+-----------------------------+...|..
....................................|..
..+-----------------------------+...|..
..|            Node             +<--+..
..+-----------------------------+......
..| [+] int:           m_data   |......
..| [+] Node*:         m_next   +---+..
..+-----------------------------+...|..
....................................v..
...................................[X].
.......................................

özet

Bir Bağlantılı Listede değişken miktarda öğe olduğundan, bellek gerektiği gibi ve mevcut olduğu şekilde tahsis edilir.

GÜNCELLEME:

@Haccks'ın gönderisinde yorum yaptığı gibi ayrıca bahsetmeye değer.

Bazen referanslar veya nesne işaretçileri, iç içe geçmiş öğeleri gösterir ("UML Oluşturma" olarak da bilinir).

Ve bazen referanslar veya nesne işaretçileri harici öğeleri belirtir ("UML Toplama" olarak da bilinir).

Ancak, aynı sınıftaki iç içe geçmiş öğeler "işaretçi yok" tekniği ile uygulanamaz.


7

Bir yan notta, bir sınıfın veya yapının ilk üyesi bir sonraki işaretçi ise (bu nedenle, bir sınıfın veya yapının ilk üyesi olmadığı anlamına gelen bir sınıfın herhangi bir sanal işlevi veya başka bir özelliği), o zaman siz sadece bir sonraki işaretçi ile "temel" bir sınıf veya yapı kullanabilir ve ekleme, önce ekleme, önden alma gibi temel bağlantılı liste işlemleri için ortak kod kullanabilir. Bunun nedeni, C / C ++ 'nın bir sınıfın veya yapının ilk üyesinin adresinin sınıf veya yapının adresiyle aynı olduğunu garanti etmesidir. Temel düğüm sınıfı veya yapı, yalnızca temel bağlantılı liste işlevleri tarafından kullanılacak bir sonraki işaretçiye sahip olacaktır, daha sonra, temel düğüm türü ile "türetilmiş" düğüm türleri arasında dönüştürme yapmak için gerektiğinde tipleme kullanılacaktır. Yan not - C ++ 'da, temel düğüm sınıfının yalnızca bir sonraki işaretçisi varsa,


6

Bağlantılı bir listede işaretçi kullanmak neden daha iyidir?

Bunun nedeni, bir Nodenesne oluşturduğunuzda , derleyicinin bu nesne için bellek ayırması ve bunun için nesnenin boyutunun hesaplanmasıdır.
Herhangi bir tip için işaretçi boyutu derleyici tarafından bilinir ve bu nedenle nesnenin kendine referanslı işaretçi boyutu hesaplanabilir.

Eğer Node m_nodebunun yerine kullanılan daha sonra derleyici büyüklüğünde hiçbir fikri yok Nodeve bir sıkışmış olacak sonsuz özyinelemeye hesaplama sizeof(Node). Her zaman unutmayın: Bir sınıf kendi türünden bir üye içeremez .


5

Çünkü bu C ++ 'da

int main (..)
{
    MyClass myObject;

    // or

    MyClass * myObjectPointer = new MyClass();

    ..
}

Java'da buna eşdeğerdir

public static void main (..)
{
    MyClass myObjectReference = new MyClass();
}

burada her ikisi MyClassde varsayılan kurucuyu kullanarak yeni bir nesne oluşturur.


0

Bağlantılı listeler, düğümleri düğümlerin içinde depolamak yerine neden işaretçiler kullanıyor?

Elbette önemsiz bir cevap var.

Onlar olmasaydı bağlantı bir işaretçi tarafından sonraki bir düğüm, onlar olmaz listeleri bağlantılı .

Bağlı listelerin bir şey olarak varlığı, nesneleri birbirine zincirleyebilmek istememizdir. Örneğin: zaten bir yerden bir nesnemiz var. Şimdi bu gerçek nesneyi (bir kopyasını değil) örneğin bir sıranın sonuna koymak istiyoruz. Bu, zaten kuyrukta bulunan son elemandan eklediğimiz girdiye bir bağlantı eklenerek elde edilir . Makine terimleriyle, bir sonraki öğenin adresiyle bir kelimeyi doldurmaktır.

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.