Mengapa daftar tertaut menggunakan pointer daripada menyimpan node di dalam node

121

Saya telah bekerja dengan daftar tertaut sebelumnya secara ekstensif di Java, tetapi saya sangat baru mengenal C ++. Saya menggunakan kelas node ini yang diberikan kepada saya dalam sebuah proyek dengan baik

class Node
{
  public:
   Node(int data);

   int m_data;
   Node *m_next;
};

tapi saya punya satu pertanyaan yang tidak dijawab dengan baik. Mengapa perlu digunakan

Node *m_next;

untuk menunjuk ke node berikutnya dalam daftar, bukan

Node m_next;

Saya mengerti bahwa lebih baik menggunakan versi pointer; Saya tidak akan memperdebatkan fakta, tapi saya tidak tahu mengapa itu lebih baik. Saya mendapat jawaban yang tidak begitu jelas tentang bagaimana penunjuk lebih baik untuk alokasi memori, dan saya bertanya-tanya apakah ada orang di sini yang dapat membantu saya memahaminya dengan lebih baik.

m0meni.dll
sumber
14
@self Maafkan saya? Mengapa bahasa di mana everthing adalah penunjuk tidak memiliki daftar tertaut?
Angew tidak lagi bangga dengan SO
41
Penting untuk dicatat bagaimana C dan C ++ berbeda dari Java dalam hal referensi objek vs. Node m_nextbukan referensi ke node, itu penyimpanan untuk keseluruhan Nodeitu sendiri.
Brian Cain
41
@self Java memang memiliki petunjuk yang tidak Anda gunakan secara eksplisit.
m0meni
27
Kura semua jalan ke bawah adalah tidak pilihan. Kegilaan itu harus berakhir di suatu tempat.
WhozCraig
26
Harap lupakan semua yang Anda ketahui tentang Java. C ++ dan Java menangani memori dengan cara yang berbeda secara fundamental. Lihat pertanyaan ini untuk memilih rekomendasi buku , dan bacalah. Anda akan sangat membantu kami.
Rob K

Jawaban:

218

Ini tidak hanya lebih baik, itu satu-satunya cara yang mungkin.

Jika Anda menyimpan Node objek di dalamnya, apa yang akan Anda lakukan sizeof(Node)? Itu akan menjadi sizeof(int) + sizeof(Node), yang akan sama dengan sizeof(int) + (sizeof(int) + sizeof(Node)), yang akan sama dengan sizeof(int) + (sizeof(int) + (sizeof(int) + sizeof(Node))), dll. Hingga tak terbatas.

Objek seperti itu tidak mungkin ada. Tidak mungkin .

emlai
sumber
25
* Kecuali jika dievaluasi dengan malas. Daftar tak terbatas dimungkinkan, hanya saja tidak dengan evaluasi ketat.
Carcigenicate
55
@Carcigenicate ini bukan tentang mengevaluasi / menjalankan beberapa fungsi pada objek Node - ini tentang tata letak memori dari setiap instance Node, yang harus ditentukan pada waktu kompilasi, sebelum evaluasi apa pun dapat terjadi.
Peteris
6
@DavidK Secara logis tidak mungkin melakukan ini. Anda memerlukan penunjuk (yah benar-benar tipuan) di sini - pasti bahasa dapat menyembunyikannya dari Anda, tetapi pada akhirnya, tidak ada cara lain.
Voo
2
@Dvid aku bingung. Pertama Anda setuju bahwa secara logis tidak mungkin, tetapi kemudian Anda ingin merenungkannya? Hapus apa pun dari C atau C ++ - tidak mungkin dalam bahasa apa pun Anda bisa bermimpi sejauh yang saya bisa lihat. Struktur itu menurut definisi adalah rekursi tak terbatas dan tanpa tingkat tipuan tertentu kita tidak dapat memecahkannya.
Voo
13
@benjamin Saya benar-benar menunjukkan (karena saya tahu jika tidak seseorang akan mengemukakan ini - yah tidak membantu) bahwa Haskell mengalokasikan thunks pada waktu pembuatan dan karenanya ini berfungsi karena thunk itu memberi kita tipuan yang kita butuhkan. Ini hanyalah penunjuk dengan data tambahan yang disamarkan ...
Voo
178

Di Jawa

Node m_node

menyimpan pointer ke node lain. Anda tidak punya pilihan tentang itu. Di C ++

Node *m_node

artinya sama. Perbedaannya adalah bahwa dalam C ++ Anda sebenarnya dapat menyimpan objek sebagai lawan penunjuk ke sana. Itulah mengapa Anda harus mengatakan Anda menginginkan penunjuk. Di C ++:

Node m_node

artinya simpan simpul di sini (dan itu jelas tidak bisa berfungsi untuk daftar - Anda berakhir dengan struktur yang ditentukan secara rekursif).

pm100
sumber
2
@SalmanA Saya sudah tahu ini. Saya hanya ingin tahu mengapa itu tidak akan berhasil tanpa penunjuk yang merupakan jawaban yang diterima menjelaskan dengan lebih baik.
m0meni
3
@ AR7 Keduanya memberikan penjelasan yang sama, hanya dengan dua pendekatan berbeda. Jika Anda mendeklarasikannya sebagai variabel "biasa", maka pertama kali konstruktor dipanggil, itu akan membuat instance baru. Tetapi sebelum itu selesai membuat instance - sebelum konstruktor yang pertama selesai - Nodekonstruktor milik anggota akan dipanggil, yang akan membuat instance baru lainnya ... dan Anda akan mendapatkan rekursi semu tanpa akhir. Ini tidak benar-benar begitu banyak masalah ukuran dalam hal benar-benar ketat dan literal, karena merupakan masalah kinerja.
Panzercrisis
Tapi semua yang Anda inginkan hanyalah cara untuk menunjukkan siapa yang berikutnya dalam daftar, bukan Nodeyang benar-benar di dalam yang pertama Node. Jadi Anda membuat pointer, yang pada dasarnya adalah cara Java menangani objek, bukan primitif. Saat Anda memanggil metode atau membuat variabel, Java tidak menyimpan salinan objek atau bahkan objek itu sendiri; itu menyimpan referensi ke sebuah objek, yang pada dasarnya adalah sebuah penunjuk dengan sedikit sarung tangan anak-anak yang melilitnya. Inilah yang pada dasarnya dikatakan oleh kedua jawaban tersebut.
Panzercrisis
ini bukan masalah ukuran atau kecepatan - ini masalah ketidakmungkinan. Objek Node yang disertakan akan menyertakan objek Node yang akan menyertakan objek Node ... Bahkan tidak mungkin untuk mengkompilasinya
pm100
3
@Panzercrisis Saya sadar bahwa mereka berdua memberikan penjelasan yang sama. Pendekatan ini, bagaimanapun, tidak begitu membantu saya karena berfokus pada apa yang sudah saya pahami: bagaimana pointer bekerja di C ++ dan bagaimana pointer ditangani di Java. Jawaban yang diterima ditujukan secara khusus mengapa tidak menggunakan penunjuk tidak mungkin karena ukurannya tidak dapat dihitung. Di sisi lain, yang ini membuatnya lebih samar sebagai "struktur yang didefinisikan secara rekursif." PS penjelasan Anda yang baru saja Anda tulis menjelaskannya lebih baik dari keduanya: D.
m0meni
38

C ++ bukan Java. Saat Anda menulis

Node m_next;

di Jawa, itu sama dengan menulis

Node* m_next;

di C ++. Di Java, penunjuk bersifat implisit, di C ++ bersifat eksplisit. Jika Anda menulis

Node m_next;

di C ++, Anda meletakkan sebuah instance Nodedi sana di dalam objek yang Anda definisikan. Itu selalu ada dan tidak dapat dihilangkan, tidak dapat dialokasikan newdan tidak dapat dihapus. Efek ini tidak mungkin dicapai di Java, dan ini sama sekali berbeda dari apa yang dilakukan Java dengan sintaks yang sama.

cmaster - kembalikan monica
sumber
1
Untuk mendapatkan sesuatu yang serupa di Java mungkin akan "meluas" jika SuperNode memperluas Node, SuperNodes menyertakan semua Atribut Node dan harus mencadangkan semua ruang tambahan. Jadi di Java Anda tidak dapat melakukan "Node extends Node"
Falco
@Falco Benar, warisan adalah bentuk penyertaan kelas dasar di tempat. Namun, karena Java tidak mengizinkan multiple inheritance (tidak seperti C ++), Anda hanya dapat menarik instance dari satu class yang sudah ada sebelumnya melalui inheritance. Itulah mengapa saya tidak akan menganggap warisan sebagai pengganti penyertaan anggota di tempat.
cmaster
27

Anda menggunakan pointer, jika tidak kode Anda:

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

... akan tidak mengkompilasi, karena compiler tidak dapat menghitung ukuran Node. Ini karena ia bergantung pada dirinya sendiri - yang berarti kompilator tidak dapat memutuskan berapa banyak memori yang akan dikonsumsi.

Nawaz
sumber
5
Lebih buruk lagi, tidak ada ukuran yang valid: Jika k == sizeof(Node)penahanan dan tipe Anda memiliki data, ia juga harus menahannya sizeof(Node) = k + sizeof(Data) = sizeof(Node) + sizeof(Data)dan kemudian sizeof(Node) > sizeof(Node).
bitmask
4
@bitmask tidak ada ukuran yang valid dalam bilangan real . Jika Anda mengizinkan transinfinites, aleph_0berfungsi. (Hanya terlalu bertele-tele :-))
k_g
2
@k_g Nah, standar C / C ++ mengamanatkan bahwa nilai yang dikembalikan sizeofadalah tipe integral unsigned, jadi ada harapan ukuran transfinite atau bahkan real. (menjadi lebih bertele-tele!: p)
Thomas
@ Thomas: Seseorang bahkan mungkin menunjukkan bahwa ada bahkan Bilangan Alami. (Melampaui -pedantik: p)
bitmask
1
Faktanya, Nodebahkan tidak ditentukan sebelum akhir cuplikan ini, jadi Anda tidak dapat menggunakannya di dalam. Mengizinkan seseorang untuk secara implisit mendeklarasikan pointer ke kelas yang belum dideklarasikan adalah sedikit cheat yang diizinkan oleh bahasa untuk membuat struktur seperti itu mungkin, tanpa perlu secara eksplisit melemparkan pointer sepanjang waktu.
osa
13

The recent ( Node m_next) harus berisi node. Itu tidak akan menunjukkannya. Dan kemudian tidak akan ada tautan elemen.

wallyk
sumber
3
Lebih buruk lagi, secara logis tidak mungkin sebuah objek mengandung sesuatu dari tipe yang sama.
Mike Seymour
Bukankah secara teknis masih ada yang menghubungkan karena itu akan menjadi simpul yang berisi simpul yang berisi simpul dan seterusnya?
m0meni
9
@ AR7: Tidak, penahanan berarti secara harfiah di dalam objek, tidak terkait dengannya.
Mike Seymour
9

Pendekatan yang Anda gambarkan tidak hanya kompatibel dengan C ++, tetapi juga dengan (kebanyakan) bahasa subset C-nya . Mempelajari cara mengembangkan daftar-tertaut gaya-C adalah cara yang baik untuk memperkenalkan diri Anda pada teknik pemrograman tingkat rendah (seperti manajemen memori manual), tetapi secara umum ini bukan praktik terbaik untuk pengembangan C ++ modern.

Di bawah ini, saya telah menerapkan empat variasi tentang cara mengelola daftar item di C ++.

  1. raw_pointer_demomenggunakan pendekatan yang sama seperti milik Anda - manajemen memori manual diperlukan dengan penggunaan pointer mentah. Penggunaan C ++ di sini hanya untuk gula sintaksis , dan pendekatan yang digunakan kompatibel dengan bahasa C.
  2. Dalam shared_pointer_demopengelolaan daftar masih dilakukan secara manual, namun pengelolaan memori dilakukan secara otomatis (tidak menggunakan raw pointer). Ini sangat mirip dengan apa yang mungkin Anda alami dengan Java.
  3. std_list_demomenggunakan listwadah pustaka standar . Ini menunjukkan betapa lebih mudahnya hal-hal jika Anda mengandalkan pustaka yang ada daripada menggulirkan milik Anda sendiri.
  4. std_vector_demomenggunakan vectorwadah pustaka standar . Ini mengelola penyimpanan daftar dalam satu alokasi memori yang berdekatan. Dengan kata lain, tidak ada petunjuk ke elemen individu. Untuk kasus tertentu yang agak ekstrem, ini mungkin menjadi sangat tidak efisien. Namun, untuk kasus umum, ini adalah praktik terbaik yang direkomendasikan untuk pengelolaan daftar di C ++ .

Catatan: Dari semua ini, hanya yang raw_pointer_demobenar - benar mengharuskan daftar tersebut dihancurkan secara eksplisit untuk menghindari memori "bocor". Tiga metode lainnya akan secara otomatis menghancurkan daftar dan isinya ketika wadah keluar dari ruang lingkup (di akhir fungsi). Intinya adalah: C ++ mampu menjadi sangat "mirip Java" dalam hal ini - tetapi hanya jika Anda memilih untuk mengembangkan program menggunakan alat tingkat tinggi yang Anda inginkan.


/*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();
}
Brent Bradburn
sumber
The Node_referencedeklarasi di atas alamat salah satu perbedaan bahasa tingkat menarik yang paling antara Jawa dan C ++. Di Java, mendeklarasikan objek berjenis Nodeakan secara implisit menggunakan referensi ke objek yang dialokasikan secara terpisah. Di C ++, Anda memiliki pilihan alokasi referensi (pointer) vs. langsung (stack) - jadi Anda harus menangani perbedaannya secara eksplisit. Dalam kebanyakan kasus, Anda akan menggunakan alokasi langsung, meskipun tidak untuk elemen daftar.
Brent Bradburn
Tidak tahu mengapa saya juga tidak merekomendasikan kemungkinan std :: deque .
Brent Bradburn
8

Gambaran

Ada 2 cara untuk mereferensikan dan mengalokasikan objek di C ++, sedangkan di Java hanya ada satu cara.

Untuk menjelaskan hal ini, diagram berikut menunjukkan bagaimana objek disimpan dalam memori.

1.1 C ++ Item tanpa petunjuk

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       | |..
..| +-----------------------------+ |..
..+---------------------------------+..
.......................................

Peringatan : Sintaks C ++ yang digunakan dalam contoh ini, mirip dengan sintaks di Java. Tapi, alokasi memorinya berbeda.

1.2 Item C ++ menggunakan pointer

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 (...)

Jika Anda memeriksa perbedaan antara kedua cara tersebut, Anda akan melihat, bahwa pada teknik pertama, item alamat dialokasikan dalam pelanggan, sedangkan cara kedua, Anda harus membuat setiap alamat secara eksplisit.

Peringatan: Java mengalokasikan objek dalam memori seperti teknik kedua ini, tetapi sintaksnya seperti cara pertama, yang mungkin membingungkan pendatang baru untuk "C ++".

Penerapan

Jadi contoh daftar Anda bisa jadi mirip dengan contoh berikut.

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].
.......................................

Ringkasan

Karena Daftar Berantai memiliki jumlah item yang bervariasi, memori dialokasikan sesuai kebutuhan, dan, sebagaimana tersedia.

MEMPERBARUI:

Juga layak untuk disebutkan, karena @haccks berkomentar di postingannya.

Terkadang, referensi atau penunjuk objek, menunjukkan item bersarang (alias "Komposisi UML").

Dan terkadang, referensi atau penunjuk objek, menunjukkan item eksternal (alias "Agregasi UML").

Namun, item bertingkat dari kelas yang sama, tidak dapat diterapkan dengan teknik "tanpa penunjuk".

umlcat
sumber
7

Di samping catatan, jika anggota pertama kelas atau struct adalah penunjuk berikutnya (jadi tidak ada fungsi virtual atau fitur lain dari kelas yang berarti next bukan anggota pertama kelas atau struct), maka Anda dapat menggunakan kelas atau struktur "dasar" hanya dengan penunjuk berikutnya, dan menggunakan kode umum untuk operasi daftar tertaut dasar seperti menambahkan, menyisipkan sebelumnya, mengambil dari depan, .... Ini karena C / C ++ menjamin bahwa alamat anggota pertama kelas atau struktur sama dengan alamat kelas atau struktur tersebut. Kelas atau struct node dasar hanya akan memiliki pointer berikutnya untuk digunakan oleh fungsi daftar tertaut dasar, kemudian typecasting akan digunakan sesuai kebutuhan untuk mengubah antara jenis node dasar dan jenis node "turunan". Catatan samping - dalam C ++, jika kelas simpul dasar hanya memiliki penunjuk berikutnya,

rcgldr.dll
sumber
6

Mengapa lebih baik menggunakan pointer dalam daftar tertaut?

Alasannya adalah ketika Anda membuat sebuah Nodeobjek, compiler harus mengalokasikan memori untuk objek tersebut dan untuk itu ukuran objek akan dihitung.
Ukuran pointer ke tipe apa pun diketahui kompiler dan oleh karena itu dengan ukuran pointer referensi sendiri objek dapat dihitung.

Jika Node m_nodedigunakan, maka compiler tidak tahu tentang ukuran Nodedan akan terjebak dalam rekursi penghitungan yang tak terbatassizeof(Node) . Selalu ingat: kelas tidak dapat berisi anggota dari tipenya sendiri .

haccks
sumber
5

Karena ini di C ++

int main (..)
{
    MyClass myObject;

    // or

    MyClass * myObjectPointer = new MyClass();

    ..
}

setara dengan ini di Jawa

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

di mana keduanya membuat objek baru MyClassmenggunakan konstruktor default.

Khaled.K
sumber
0

Mengapa daftar tertaut menggunakan pointer daripada menyimpan node di dalam node?

Tentu ada jawaban yang sepele.

Jika mereka tidak menautkan satu node ke node berikutnya dengan sebuah pointer, mereka tidak akan ditautkan ke daftar .

Keberadaan daftar tertaut sebagai suatu hal karena kami ingin dapat menghubungkan objek bersama. Misalnya: kita sudah memiliki objek dari suatu tempat. Kami sekarang ingin meletakkan objek sebenarnya (bukan salinan) di akhir antrian, misalnya. Itu dicapai dengan menambahkan tautan dari elemen terakhir yang sudah ada di antrian ke entri yang kami tambahkan. Dalam istilah mesin, itu mengisi kata dengan alamat elemen berikutnya.

pengguna13784117
sumber