Pertanyaan Mengapa saya harus menggunakan pointer daripada objek itu sendiri?


Saya berasal dari latar belakang Java dan sudah mulai bekerja dengan objek di C ++. Tapi satu hal yang terjadi pada saya adalah bahwa orang sering menggunakan pointer ke objek daripada objek itu sendiri, misalnya pernyataan ini:

Object *myObject = new Object;

daripada:

Object myObject;

Atau alih-alih menggunakan fungsi, katakanlah testFunc(), seperti ini:

myObject.testFunc();

kita harus menulis:

myObject->testFunc();

Tetapi saya tidak tahu mengapa kita harus melakukannya dengan cara ini. Saya akan menganggap itu ada hubungannya dengan efisiensi dan kecepatan karena kita mendapatkan akses langsung ke alamat memori. Apakah saya benar?


1333
2018-03-03 11:54


asal


Jawaban:


Sangat disayangkan bahwa Anda melihat alokasi dinamis begitu sering. Itu hanya menunjukkan berapa banyak programmer C ++ yang buruk.

Dalam arti, Anda memiliki dua pertanyaan yang dibundel menjadi satu. Yang pertama adalah kapan kita harus menggunakan alokasi dinamis (menggunakan new)? Yang kedua adalah kapan kita harus menggunakan pointer?

Pesan dibawa pulang yang penting adalah Anda harus melakukannya selalu gunakan alat yang tepat untuk pekerjaan itu. Di hampir semua situasi, ada sesuatu yang lebih tepat dan lebih aman daripada melakukan alokasi dinamis manual dan / atau menggunakan pointer mentah.

Alokasi dinamis

Dalam pertanyaan Anda, Anda telah menunjukkan dua cara untuk membuat objek. Perbedaan utama adalah durasi penyimpanan objek. Saat melakukan Object myObject; dalam satu blok, objek dibuat dengan durasi penyimpanan otomatis, yang berarti ia akan dihancurkan secara otomatis ketika keluar dari ruang lingkup. Saat kamu melakukan new Object(), objek memiliki durasi penyimpanan dinamis, yang artinya tetap hidup sampai Anda secara eksplisit delete saya t. Anda sebaiknya hanya menggunakan durasi penyimpanan dinamis saat Anda membutuhkannya. Itu adalah, kamu harus selalu lebih suka membuat objek dengan durasi penyimpanan otomatis ketika Anda bisa.

Dua situasi utama di mana Anda mungkin memerlukan alokasi dinamis:

  1. Anda membutuhkan objek untuk hidup lebih lama dari lingkup saat ini - objek tertentu di lokasi memori tertentu, bukan salinannya. Jika Anda baik-baik saja dengan menyalin / memindahkan objek (sebagian besar waktu Anda seharusnya), Anda sebaiknya memilih objek otomatis.
  2. Anda perlu mengalokasikan banyak memori, yang dapat dengan mudah mengisi tumpukan. Akan lebih baik jika kita tidak perlu menyibukkan diri dengan ini (sebagian besar waktu Anda tidak perlu), karena itu benar-benar di luar lingkup C ++, tapi sayangnya kita harus berurusan dengan realitas sistem yang kita sedang berkembang untuk.

Ketika Anda benar-benar membutuhkan alokasi dinamis, Anda harus mengenkapsulasi dalam pointer pintar atau beberapa jenis lain yang berfungsi RAII (seperti kontainer standar). Smart pointer memberikan semantik kepemilikan objek yang dialokasikan secara dinamis. Melihat std::unique_ptr dan std::shared_ptr, sebagai contoh. Jika Anda menggunakannya dengan tepat, Anda hampir dapat sepenuhnya menghindari melakukan manajemen memori Anda sendiri (lihat Rule of Zero).

Pointer

Namun, ada penggunaan lain yang lebih umum untuk pointer mentah di luar alokasi dinamis, tetapi sebagian besar memiliki alternatif yang sebaiknya Anda pilih. Seperti sebelumnya, selalu lebih suka alternatif kecuali Anda benar-benar membutuhkan petunjuk.

  1. Anda perlu semantik referensi. Kadang-kadang Anda ingin melewatkan objek menggunakan pointer (terlepas dari bagaimana itu dialokasikan) karena Anda ingin fungsi yang Anda melewati itu memiliki akses yang objek tertentu (bukan salinannya). Namun, dalam sebagian besar situasi, Anda sebaiknya memilih jenis referensi untuk pointer, karena ini adalah khusus untuk apa mereka dirancang. Catatan ini tidak perlu tentang memperpanjang umur objek di luar lingkup saat ini, seperti dalam situasi 1 di atas. Seperti sebelumnya, jika Anda tidak keberatan dengan mengirimkan salinan objek, Anda tidak perlu semantik referensi.

  2. Anda membutuhkan polimorfisme. Anda hanya dapat memanggil fungsi polimorfik (yaitu, sesuai dengan tipe dinamis suatu objek) melalui penunjuk atau referensi ke objek. Jika itu perilaku yang Anda butuhkan, maka Anda perlu menggunakan pointer atau referensi. Sekali lagi, referensi harus lebih disukai.

  3. Anda ingin menyatakan bahwa suatu objek adalah opsional dengan mengizinkan nullptr dilewatkan ketika objek sedang dihilangkan. Jika itu argumen, Anda sebaiknya menggunakan argumen default atau fungsi yang berlebihan. Jika tidak, Anda sebaiknya menggunakan jenis yang merangkum perilaku ini, seperti std::optional (diperkenalkan pada C ++ 17 - dengan standar C ++ sebelumnya, gunakan boost::optional).

  4. Anda ingin memisahkan unit kompilasi untuk meningkatkan waktu kompilasi. Properti yang berguna dari pointer adalah bahwa Anda hanya memerlukan deklarasi maju dari tipe runcing (untuk benar-benar menggunakan objek, Anda akan membutuhkan definisi). Ini memungkinkan Anda untuk memisahkan bagian dari proses kompilasi Anda, yang dapat secara signifikan meningkatkan waktu kompilasi. Lihat Idiot idiom.

  5. Anda perlu berinteraksi dengan pustaka C atau perpustakaan C-style. Pada titik ini, Anda terpaksa menggunakan pointer mentah. Hal terbaik yang dapat Anda lakukan adalah memastikan Anda hanya membiarkan pointer mentah Anda lepas pada saat-saat terakhir. Anda bisa mendapatkan pointer mentah dari pointer pintar, misalnya, dengan menggunakan nya get fungsi anggota. Jika sebuah perpustakaan melakukan beberapa alokasi untuk Anda yang mengharapkan Anda untuk membatalkan alokasi melalui sebuah pegangan, Anda sering dapat membungkus gagang tombol dalam penunjuk pintar dengan deleter khusus yang akan membatalkan objek dengan tepat.


1346
2018-03-03 12:06



Ada banyak kasus penggunaan untuk pointer.

Perilaku polimorfik. Untuk tipe polimorfik, pointer (atau referensi) digunakan untuk menghindari pemotongan:

class Base { ... };
class Derived : public Base { ... };

void fun(Base b) { ... }
void gun(Base* b) { ... }
void hun(Base& b) { ... }

Derived d;
fun(d);    // oops, all Derived parts silently "sliced" off
gun(&d);   // OK, a Derived object IS-A Base object
hun(d);    // also OK, reference also doesn't slice

Referensi semantik dan hindari menyalin. Untuk jenis non-polimorfik, pointer (atau referensi) akan menghindari menyalin objek yang berpotensi mahal

Base b;
fun(b);  // copies b, potentially expensive 
gun(&b); // takes a pointer to b, no copying
hun(b);  // regular syntax, behaves as a pointer

Perhatikan bahwa C ++ 11 memiliki semantik gerakan yang dapat menghindari banyak salinan objek mahal menjadi argumen fungsi dan sebagai nilai kembali. Tetapi menggunakan pointer pasti akan menghindari itu dan akan memungkinkan beberapa pointer pada objek yang sama (sedangkan objek hanya dapat dipindahkan dari sekali).

Pengambilan sumber daya. Membuat penunjuk ke sumber daya menggunakan new operator adalah sebuah anti-pola dalam C ++ modern. Gunakan kelas sumber daya khusus (salah satu kontainer Standar) atau a pointer pintar (std::unique_ptr<> atau std::shared_ptr<>). Mempertimbangkan:

{
    auto b = new Base;
    ...       // oops, if an exception is thrown, destructor not called!
    delete b;
}

vs.

{
    auto b = std::make_unique<Base>();
    ...       // OK, now exception safe
}

Penunjuk mentah hanya boleh digunakan sebagai "pandangan" dan bukan dalam cara apa pun yang terlibat dalam kepemilikan, baik melalui pembuatan langsung atau secara implisit melalui nilai kembali. Lihat juga Q & A ini dari FAQ C ++.

Kontrol kehidupan-waktu yang lebih halus Setiap kali pointer bersama disalin (mis. Sebagai argumen fungsi), sumber daya yang ditunjukkannya disimpan tetap hidup. Objek reguler (tidak dibuat oleh new, baik secara langsung oleh Anda atau di dalam kelas sumber daya) dihancurkan ketika keluar dari ruang lingkup.


155
2018-03-06 18:40



Ada banyak jawaban yang sangat baik untuk pertanyaan ini, termasuk kasus penggunaan penting deklarasi ke depan, polimorfisme, dll. Tetapi saya merasa bagian dari "jiwa" dari pertanyaan Anda tidak terjawab - yaitu apa arti sintaks yang berbeda di seluruh Java dan C ++.

Mari kita periksa situasi membandingkan dua bahasa:

Jawa:

Object object1 = new Object(); //A new object is allocated by Java
Object object2 = new Object(); //Another new object is allocated by Java

object1 = object2; 
//object1 now points to the object originally allocated for object2
//The object originally allocated for object1 is now "dead" - nothing points to it, so it
//will be reclaimed by the Garbage Collector.
//If either object1 or object2 is changed, the change will be reflected to the other

Setara yang paling dekat dengan ini, adalah:

C ++:

Object * object1 = new Object(); //A new object is allocated on the heap
Object * object2 = new Object(); //Another new object is allocated on the heap
delete object1;
//Since C++ does not have a garbage collector, if we don't do that, the next line would 
//cause a "memory leak", i.e. a piece of claimed memory that the app cannot use 
//and that we have no way to reclaim...

object1 = object2; //Same as Java, object1 points to object2.

Mari kita lihat cara C ++ alternatif:

Object object1; //A new object is allocated on the STACK
Object object2; //Another new object is allocated on the STACK
object1 = object2;//!!!! This is different! The CONTENTS of object2 are COPIED onto object1,
//using the "copy assignment operator", the definition of operator =.
//But, the two objects are still different. Change one, the other remains unchanged.
//Also, the objects get automatically destroyed once the function returns...

Cara terbaik untuk memikirkannya adalah - kurang lebih - Java (secara implisit) menangani pointer ke objek, sementara C ++ dapat menangani pointer ke objek, atau objek itu sendiri. Ada pengecualian untuk ini - misalnya, jika Anda menyatakan Java "primitif" jenis, mereka adalah nilai-nilai aktual yang disalin, dan bukan pointer. Begitu,

Jawa:

int object1; //An integer is allocated on the stack.
int object2; //Another integer is allocated on the stack.
object1 = object2; //The value of object2 is copied to object1.

Yang mengatakan, menggunakan pointer TIDAK perlu baik cara yang benar atau salah untuk menangani hal-hal; namun jawaban lain telah mencakup hal itu dengan memuaskan. Gagasan umum adalah bahwa di C ++ Anda memiliki lebih banyak kontrol pada masa hidup objek, dan di mana mereka akan hidup.

Ambil home point - the Object * object = new Object() konstruk sebenarnya apa yang paling dekat dengan semantik khas Jawa (atau C # dalam hal ini).


111
2018-03-03 14:34



Alasan bagus lainnya untuk menggunakan pointer adalah untuk deklarasi ke depan. Dalam proyek yang cukup besar, mereka dapat mempercepat waktu kompilasi.


73
2018-03-07 07:30



Kata pengantar

Java tidak seperti C ++, bertentangan dengan hype. Mesin hype Java ingin Anda percaya bahwa karena Java memiliki C ++ seperti sintaks, maka bahasanya mirip. Tidak ada yang bisa lebih jauh dari kebenaran. Kesalahan informasi ini adalah bagian dari alasan mengapa pemrogram Java menggunakan C ++ dan menggunakan sintaks yang mirip Java tanpa memahami implikasi dari kode mereka.

Selanjutnya kita pergi

Tetapi saya tidak tahu mengapa kita harus melakukannya dengan cara ini. Saya akan menganggapnya   harus dilakukan dengan efisiensi dan kecepatan karena kami mendapatkan akses langsung ke   alamat memori. Apakah saya benar?

Sebaliknya, sebenarnya. Tumpukannya jauh lebih lambat dari tumpukan, karena tumpukan sangat sederhana dibandingkan dengan tumpukan. Variabel penyimpanan otomatis (alias variabel tumpukan) telah dirusak oleh perusaknya setelah keluar dari ruang lingkup. Sebagai contoh:

{
    std::string s;
}
// s is destroyed here

Di sisi lain, jika Anda menggunakan pointer yang dialokasikan secara dinamis, destruktornya harus dipanggil secara manual. deletepanggilan destructor ini untuk Anda.

{
    std::string* s = new std::string;
}
delete s; // destructor called

Ini tidak ada hubungannya dengan new sintaks lazim di C # dan Java. Mereka digunakan untuk tujuan yang sama sekali berbeda.

Manfaat alokasi dinamis

1. Anda tidak harus mengetahui ukuran dari array sebelumnya

Salah satu masalah pertama yang dijalankan oleh banyak programmer C adalah bahwa ketika mereka menerima masukan acak dari pengguna, Anda hanya dapat mengalokasikan ukuran tetap untuk variabel stack. Anda juga tidak dapat mengubah ukuran larik. Sebagai contoh:

char buffer[100];
std::cin >> buffer;
// bad input = buffer overflow

Tentu saja, jika Anda menggunakan std::string sebagai gantinya, std::string internal mengubah ukuran dirinya sendiri sehingga seharusnya tidak menjadi masalah. Tetapi pada dasarnya solusi untuk masalah ini adalah alokasi dinamis. Anda dapat mengalokasikan memori dinamis berdasarkan masukan dari pengguna, misalnya:

int * pointer;
std::cout << "How many items do you need?";
std::cin >> n;
pointer = new int[n];

Catatan sampingan: Satu kesalahan yang banyak dilakukan pemula adalah penggunaan   array panjang variabel. Ini adalah ekstensi GNU dan juga satu dalam Clang   karena mereka mencerminkan banyak ekstensi GCC. Maka berikut ini    int arr[n] tidak boleh diandalkan.

Karena tumpukan lebih besar dari tumpukan, seseorang dapat mengalokasikan / mengalokasikan sebanyak mungkin memori sesuai kebutuhannya, sedangkan tumpukan memiliki batasan.

2. Array bukan pointer

Bagaimana ini manfaat yang Anda tanyakan? Jawabannya akan menjadi jelas setelah Anda memahami kebingungan / mitos di balik array dan pointer. Umumnya diasumsikan bahwa mereka sama, tetapi tidak. Mitos ini berasal dari fakta bahwa pointer dapat di-subscript seperti array dan karena peluruhan array ke pointer di tingkat atas dalam deklarasi fungsi. Namun, setelah sebuah array meluruh menjadi penunjuk, penunjuk hilang sizeof informasi. Begitu sizeof(pointer) akan memberikan ukuran pointer dalam byte, yang biasanya 8 byte pada sistem 64-bit.

Anda tidak dapat menetapkan ke array, hanya menginisialisasi mereka. Sebagai contoh:

int arr[5] = {1, 2, 3, 4, 5}; // initialization 
int arr[] = {1, 2, 3, 4, 5}; // The standard dictates that the size of the array
                             // be given by the amount of members in the initializer  
arr = { 1, 2, 3, 4, 5 }; // ERROR

Di sisi lain, Anda dapat melakukan apa pun yang Anda inginkan dengan pointer. Sayangnya, karena perbedaan antara pointer dan array melambaikan tangan di Java dan C #, pemula tidak mengerti perbedaannya.

3. Polimorfisme

Java dan C # memiliki fasilitas yang memungkinkan Anda memperlakukan objek sebagai objek lain, misalnya menggunakan as kata kunci. Jadi, jika seseorang ingin mengobati Entity objek sebagai Player objek, yang bisa dilakukan Player player = Entity as Player; Ini sangat berguna jika Anda bermaksud memanggil fungsi pada wadah homogen yang seharusnya hanya berlaku untuk jenis tertentu. Fungsinya dapat dicapai dengan cara yang sama di bawah ini:

std::vector<Base*> vector;
vector.push_back(&square);
vector.push_back(&triangle);
for (auto& e : vector)
{
     auto test = dynamic_cast<Triangle*>(e); // I only care about triangles
     if (!test) // not a triangle
        e.GenericFunction();
     else
        e.TriangleOnlyMagic();
}

Jadi katakanlah jika hanya Segitiga memiliki fungsi Putar, itu akan menjadi kesalahan kompilator jika Anda mencoba untuk memanggilnya pada semua objek dari kelas. Menggunakan dynamic_cast, Anda dapat mensimulasikan as kata kunci. Agar jelas, jika pemain gagal, ia mengembalikan penunjuk tidak valid. Begitu !test pada dasarnya adalah singkatan untuk memeriksa jika test NULL atau penunjuk tidak valid, yang berarti gips gagal.

Manfaat variabel otomatis

Setelah melihat semua hal hebat yang dapat dilakukan oleh alokasi dinamis, Anda mungkin bertanya-tanya mengapa tidak ada orang yang TIDAK menggunakan alokasi dinamis setiap saat? Aku sudah memberitahumu satu alasan, heapnya lambat. Dan jika Anda tidak membutuhkan semua memori itu, Anda tidak boleh menyalahgunakannya. Jadi di sini ada beberapa kerugian tanpa urutan tertentu:

  • Ini rawan kesalahan. Alokasi memori manual berbahaya dan Anda rentan terhadap kebocoran. Jika Anda tidak mahir menggunakan debugger atau valgrind (alat kebocoran memori), Anda dapat menarik rambut Anda keluar dari kepala Anda. Untungnya idiom-idiom RAII dan petunjuk-petunjuk cerdas meringankan ini sedikit, tetapi Anda harus terbiasa dengan praktik-praktik seperti The Rule Of Three dan The Rule Of Five. Banyak informasi yang harus diambil, dan pemula yang tidak tahu atau tidak peduli akan jatuh ke dalam perangkap ini.

  • Itu tidak perlu. Tidak seperti Java dan C # di mana itu adalah idiomatik untuk menggunakan new kata kunci di mana-mana, di C ++, Anda hanya harus menggunakannya jika perlu. Ungkapan yang umum berlaku, semuanya tampak seperti paku jika Anda memiliki palu. Sedangkan pemula yang memulai dengan C ++ takut akan pointer dan belajar menggunakan variabel stack dengan kebiasaan, Java dan C # programmer mulai dengan menggunakan pointer tanpa memahaminya! Itu benar-benar melangkah dengan kaki yang salah. Anda harus meninggalkan semua yang Anda tahu karena sintaksnya adalah satu hal, belajar bahasa adalah hal lain.

1. (N) RVO - Aka, (Dinamakan) Pengoptimalan Nilai Pengembalian

Salah satu pengoptimalan yang dilakukan banyak kompiler adalah hal-hal yang disebut peniadaan bunyi dlm ucapan dan optimasi nilai kembali. Hal-hal ini dapat menghindarkan copys yang tidak diperlukan yang berguna untuk objek yang sangat besar, seperti vektor yang mengandung banyak elemen. Biasanya praktik umum adalah menggunakan pointer ke transfer kepemilikan daripada menyalin objek besar pindah mereka di sekitar. Ini telah menyebabkan dimulainya memindahkan semantik dan pointer pintar.

Jika Anda menggunakan pointer, (N) RVO tidak TIDAK terjadi. Ini lebih bermanfaat dan kurang rawan kesalahan untuk memanfaatkan (N) RVO daripada mengembalikan atau meneruskan pointer jika Anda khawatir tentang pengoptimalan. Kesalahan kebocoran dapat terjadi jika pemanggil suatu fungsi bertanggung jawab atas deleteing objek yang dialokasikan secara dinamis dan semacamnya. Sulit untuk melacak kepemilikan suatu objek jika pointer dilewatkan seperti kentang panas. Cukup gunakan variabel tumpukan karena lebih sederhana dan lebih baik.


62
2018-03-07 10:00



C ++ memberi Anda tiga cara untuk mengirimkan objek: dengan pointer, dengan referensi, dan berdasarkan nilai. Java membatasi Anda dengan yang terakhir (satu-satunya pengecualian adalah tipe primitif seperti int, boolean dll). Jika Anda ingin menggunakan C ++ tidak hanya seperti mainan aneh, maka Anda sebaiknya mengetahui perbedaan antara ketiga cara ini.

Jawa berpura-pura bahwa tidak ada masalah seperti 'siapa dan kapan harus menghancurkan ini?'. Jawabannya adalah: Kolektor Sampah, Hebat dan Mengerikan. Namun demikian, itu tidak dapat memberikan perlindungan 100% terhadap kebocoran memori (ya, Jawa bisa memori bocor). Sebenarnya, GC memberi Anda rasa aman yang salah. Semakin besar SUV Anda, semakin lama jalan Anda menuju evakuasi.

C ++ membuat Anda berhadap-hadapan dengan manajemen siklus hidup objek. Nah, ada cara untuk menghadapinya (pointer pintar keluarga, QObject di Qt dan sebagainya), tetapi tidak satupun dari mereka dapat digunakan dalam cara 'api dan melupakan' seperti GC: Anda harus selaluperlu diingat penanganan memori. Tidak hanya Anda harus peduli menghancurkan objek, Anda juga harus menghindari menghancurkan objek yang sama lebih dari satu kali.

Belum takut? Ok: referensi siklik - tangani mereka sendiri, manusia. Dan ingat: bunuh setiap objek tepat satu kali, kami C ++ runtime tidak suka orang yang mengotori mayat, meninggalkan yang mati sendirian.

Jadi, kembali ke pertanyaan Anda.

Ketika Anda melewati objek Anda dengan nilai, bukan dengan penunjuk atau dengan referensi, Anda menyalin objek (seluruh objek, apakah itu beberapa byte atau dump basis data yang besar - Anda cukup pintar untuk peduli untuk menghindari yang terakhir, ' t Anda?) setiap kali Anda melakukan '='. Dan untuk mengakses anggota objek, Anda menggunakan '.' (dot).

Ketika Anda melewati objek dengan pointer, Anda hanya menyalin beberapa byte (4 pada sistem 32-bit, 8 pada yang 64-bit), yaitu - alamat objek ini. Dan untuk menunjukkan ini kepada semua orang, Anda menggunakan operator '->' yang mewah ini saat Anda mengakses anggota. Atau Anda dapat menggunakan kombinasi '*' dan '.'.

Ketika Anda menggunakan referensi, maka Anda mendapatkan pointer yang berpura-pura menjadi nilai. Ini adalah penunjuk, tetapi Anda mengakses anggota melalui '.'.

Dan, untuk meniup pikiran Anda sekali lagi: ketika Anda menyatakan beberapa variabel dipisahkan dengan koma, maka (perhatikan tangan):

  • Jenis diberikan kepada semua orang
  • Pengubah nilai / penunjuk / referensi bersifat individual

Contoh:

struct MyStruct
{
    int* someIntPointer, someInt; //here comes the surprise
    MyStruct *somePointer;
    MyStruct &someReference;
};

MyStruct s1; //we allocated an object on stack, not in heap

s1.someInt = 1; //someInt is of type 'int', not 'int*' - value/pointer modifier is individual
s1.someIntPointer = &s1.someInt;
*s1.someIntPointer = 2; //now s1.someInt has value '2'
s1.somePointer = &s1;
s1.someReference = s1; //note there is no '&' operator: reference tries to look like value
s1.somePointer->someInt = 3; //now s1.someInt has value '3'
*(s1.somePointer).someInt = 3; //same as above line
*s1.somePointer->someIntPointer = 4; //now s1.someInt has value '4'

s1.someReference.someInt = 5; //now s1.someInt has value '5'
                              //although someReference is not value, it's members are accessed through '.'

MyStruct s2 = s1; //'NO WAY' the compiler will say. Go define your '=' operator and come back.

//OK, assume we have '=' defined in MyStruct

s2.someInt = 0; //s2.someInt == 0, but s1.someInt is still 5 - it's two completely different objects, not the references to the same one

21
2018-03-03 12:00



Di C ++, objek yang dialokasikan pada stack (menggunakan Object object; pernyataan dalam blok) hanya akan hidup dalam lingkup yang mereka nyatakan. Ketika blok kode selesai eksekusi, objek dinyatakan hancur. Sedangkan jika Anda mengalokasikan memori di heap, gunakan Object* obj = new Object(), mereka terus hidup dalam tumpukan sampai Anda menelepon delete obj.

Saya akan membuat objek di heap ketika saya ingin menggunakan objek tidak hanya di blok kode yang menyatakan / mengalokasikannya.


19
2018-03-03 12:19