Apa itu smart pointer dan kapan saya harus menggunakannya?

1821

Apa itu smart pointer dan kapan saya harus menggunakannya?

Alex Reynolds
sumber
7
Lihat pertanyaan ini: <br> Smart Pointers: Atau siapa yang memiliki Anda bayi
Martin York
2
Perhatikan bahwa implementasi std :: auto_ptr di Visual Studio 2005 rusak parah. <br> http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=98871 <br> http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=101842 Gunakan tingkatkan saja.
Richard
25
Dua artikel bagus tentang hal ini: - Smart Pointer - Apa, Mengapa, Mana? - Guru Minggu Ini # 25
Lazer
1
Inilah bab Alexandrescu (gratis) tentang seluk-beluk menciptakan petunjuk pintar dari berbagai rasa: informit.com/articles/article.aspx?p=31529 Dalam implementasinya, ia menggunakan argumen templat sebagai "kebijakan" untuk menentukan atribut mana yang ia inginkan ( misalnya, penghitungan referensi), sedangkan perpustakaan standar menggunakan kelas yang terpisah. Perhatikan bahwa ia juga menulis sebelum referensi nilai tersedia untuk membuat sesuatu seperti std :: unique_ptr menjadi mungkin.
logam
Saya ingin menambahkan satu poin lagi ke pertanyaan di atas, smart pointer std :: shared_ptr tidak memiliki operator subskrip dan tidak mendukung aritmatika ponter, kita dapat menggunakan get () untuk mendapatkan pointer bawaan.
suresh m

Jawaban:

1884

MEMPERBARUI

Jawaban ini agak lama, dan karenanya menggambarkan apa yang 'baik' pada saat itu, yang merupakan petunjuk cerdas yang disediakan oleh perpustakaan Boost. Sejak C ++ 11, perpustakaan standar telah menyediakan tipe smart pointer yang memadai, dan karenanya Anda harus mendukung penggunaan std::unique_ptr, std::shared_ptrdan std::weak_ptr.

Ada juga std::auto_ptr. Itu sangat mirip dengan penunjuk cakupan, kecuali bahwa ia juga memiliki kemampuan berbahaya "khusus" untuk disalin - yang juga secara tak terduga mengalihkan kepemilikan.
Itu sudah ditinggalkan di C ++ 11 dan dihapus di C ++ 17 , jadi Anda tidak harus menggunakannya.

std::auto_ptr<MyObject> p1 (new MyObject());
std::auto_ptr<MyObject> p2 = p1; // Copy and transfer ownership. 
                                 // p1 gets set to empty!
p2->DoSomething(); // Works.
p1->DoSomething(); // Oh oh. Hopefully raises some NULL pointer exception.

JAWABAN TUA

Pointer pintar adalah kelas yang membungkus pointer C ++ 'mentah' (atau 'telanjang'), untuk mengatur masa pakai objek yang ditunjuk. Tidak ada satu pun tipe smart pointer, tetapi semuanya mencoba untuk abstrak sebuah pointer mentah dengan cara yang praktis.

Pointer pintar harus lebih disukai daripada pointer mentah. Jika Anda merasa perlu menggunakan pointer (pertimbangkan terlebih dahulu jika benar - benar melakukannya), Anda biasanya ingin menggunakan pointer pintar karena ini dapat meringankan banyak masalah dengan pointer mentah, terutama lupa untuk menghapus objek dan memori yang bocor.

Dengan pointer mentah, programmer harus secara eksplisit menghancurkan objek ketika tidak lagi berguna.

// Need to create the object to achieve some goal
MyObject* ptr = new MyObject(); 
ptr->DoSomething(); // Use the object in some way
delete ptr; // Destroy the object. Done with it.
// Wait, what if DoSomething() raises an exception...?

Pointer pintar dengan perbandingan mendefinisikan kebijakan kapan objek dihancurkan. Anda masih harus membuat objek, tetapi Anda tidak perlu lagi khawatir untuk menghancurkannya.

SomeSmartPtr<MyObject> ptr(new MyObject());
ptr->DoSomething(); // Use the object in some way.

// Destruction of the object happens, depending 
// on the policy the smart pointer class uses.

// Destruction would happen even if DoSomething() 
// raises an exception

Kebijakan paling sederhana yang digunakan melibatkan ruang lingkup objek pembungkus penunjuk pintar, seperti yang diterapkan oleh boost::scoped_ptratau std::unique_ptr.

void f()
{
    {
       std::unique_ptr<MyObject> ptr(new MyObject());
       ptr->DoSomethingUseful();
    } // ptr goes out of scope -- 
      // the MyObject is automatically destroyed.

    // ptr->Oops(); // Compile error: "ptr" not defined
                    // since it is no longer in scope.
}

Perhatikan bahwa std::unique_ptrinstance tidak dapat disalin. Ini mencegah penunjuk dihapus beberapa kali (salah). Namun, Anda dapat meneruskan referensi ke fungsi lain yang Anda panggil.

std::unique_ptrs berguna ketika Anda ingin mengikat masa pakai objek ke blok kode tertentu, atau jika Anda menyematkannya sebagai data anggota di dalam objek lain, masa pakai objek lain itu. Objek ada sampai blok kode yang berisi keluar, atau sampai objek yang berisi itu sendiri dihancurkan.

Kebijakan smart pointer yang lebih kompleks melibatkan referensi penghitungan pointer. Ini memungkinkan pointer untuk disalin. Ketika "referensi" terakhir ke objek dihancurkan, objek tersebut dihapus. Kebijakan ini diterapkan oleh boost::shared_ptrdan std::shared_ptr.

void f()
{
    typedef std::shared_ptr<MyObject> MyObjectPtr; // nice short alias
    MyObjectPtr p1; // Empty

    {
        MyObjectPtr p2(new MyObject());
        // There is now one "reference" to the created object
        p1 = p2; // Copy the pointer.
        // There are now two references to the object.
    } // p2 is destroyed, leaving one reference to the object.
} // p1 is destroyed, leaving a reference count of zero. 
  // The object is deleted.

Referensi penghitung referensi sangat berguna ketika masa pakai objek Anda jauh lebih rumit, dan tidak terikat langsung ke bagian kode tertentu atau ke objek lain.

Ada satu kelemahan dari referensi penghitung referensi - kemungkinan membuat referensi yang menggantung:

// Create the smart pointer on the heap
MyObjectPtr* pp = new MyObjectPtr(new MyObject())
// Hmm, we forgot to destroy the smart pointer,
// because of that, the object is never destroyed!

Kemungkinan lain adalah membuat referensi melingkar:

struct Owner {
   std::shared_ptr<Owner> other;
};

std::shared_ptr<Owner> p1 (new Owner());
std::shared_ptr<Owner> p2 (new Owner());
p1->other = p2; // p1 references p2
p2->other = p1; // p2 references p1

// Oops, the reference count of of p1 and p2 never goes to zero!
// The objects are never destroyed!

Untuk mengatasi masalah ini, Boost dan C ++ 11 telah mendefinisikan a weak_ptruntuk mendefinisikan referensi lemah (tidak terhitung) ke a shared_ptr.

Lloyd
sumber
7
Apakah maksud Anda std::auto_ptr<MyObject> p1 (new MyObject());alih-alih std::auto_ptr<MyObject> p1 (new Owner());?
Mateen Ulhaq
35
Jawaban yang luar biasa. Akan lebih baik jika diperbarui untuk c ++ 11. Saya menemukan jawaban ini mencari info tentang standar 11 baru dan alangkah baiknya jika pengunjung masa depan dapat menemukan info yang diperbarui. Saya tahu auto_ptr telah ditinggalkan. Saya percaya shated_ptr dan lemah_ptr ada seperti yang dijelaskan, dan saya pikir scoped_ptr sekarang unique_ptr dalam standar. Jika ini benar, bisakah jawaban ini diperbarui?
SaulBack
16
Mengatakan bahwa kemungkinan membuat referensi yang menggantung adalah kelemahan dari referensi yang dihitung adalah benar-benar gila. Referensi menggantung yang mungkin adalah kelemahan dari setiap pointer C ++ . Bahkan, justru kekurangan itulah yang dimaksudkan untuk diringankan oleh pointer cerdas .
Michael Dorst
16
Jika Anda mendeklarasikan pointer ke smart pointer (seperti yang dilakukan pada contoh) Anda dengan sadar melepaskan semua manfaat dari smart pointer. Ini bukan kelemahan atau cacat desain, ini adalah penggunaan paling konyol yang bisa dibayangkan.
Michael Dorst
3
A const std::auto_ptraman digunakan, jika Anda terjebak dengan C ++ 03. Saya menggunakannya untuk pola jerawat cukup banyak sampai saya mendapat akses ke C ++ 11.
Toby Speight
303

Inilah jawaban sederhana untuk C ++ modern hari ini (C ++ 11 dan yang lebih baru):

  • Apa itu smart pointer?
    Ini adalah tipe yang nilainya dapat digunakan seperti pointer, tetapi yang menyediakan fitur tambahan manajemen memori otomatis: Ketika pointer cerdas tidak lagi digunakan, memori yang ditunjuknya akan dibatalkan alokasi (lihat juga definisi yang lebih rinci tentang Wikipedia ).
  • Kapan saya harus menggunakannya?
    Dalam kode yang melibatkan pelacakan kepemilikan sepotong memori, mengalokasikan atau menghapus alokasi; penunjuk pintar sering menghemat kebutuhan Anda untuk melakukan hal-hal ini secara eksplisit.
  • Tapi smart pointer mana yang harus saya gunakan dalam kasus mana?
    • Gunakan std::unique_ptrsaat Anda tidak berniat menyimpan beberapa referensi ke objek yang sama. Misalnya, gunakan untuk penunjuk ke memori yang akan dialokasikan saat memasukkan beberapa cakupan dan tidak dialokasikan saat keluar dari ruang lingkup.
    • Gunakan std::shared_ptrketika Anda ingin merujuk ke objek Anda dari berbagai tempat - dan tidak ingin objek Anda tidak dialokasikan sampai semua referensi itu sendiri hilang.
    • Gunakan std::weak_ptrketika Anda ingin merujuk objek Anda dari berbagai tempat - untuk referensi yang tidak boleh diabaikan dan tidak dialokasikan (jadi mereka hanya akan mencatat objek tersebut hilang ketika Anda mencoba melakukan dereferensi).
    • Jangan gunakan boost::smart pointer atau std::auto_ptrkecuali dalam kasus khusus yang dapat Anda baca jika Anda harus.
  • Hei, aku tidak bertanya yang mana yang harus digunakan!
    Ah, tapi kamu benar-benar ingin, mengakuinya.
  • Jadi kapan saya harus menggunakan pointer biasa?
    Sebagian besar dalam kode yang tidak menyadari kepemilikan memori. Ini biasanya berada dalam fungsi yang mendapatkan pointer dari tempat lain dan tidak mengalokasikan atau menghapus alokasi, dan tidak menyimpan salinan pointer yang bertahan lebih lama dari eksekusi mereka.
einpoklum
sumber
5
Perlu dicatat bahwa meskipun pointer pintar (memiliki) membantu dengan manajemen memori yang tepat, pointer mentah (tidak memiliki) masih berguna untuk keperluan organisasi lainnya dalam struktur data. Herb Sutter memberikan presentasi yang bagus tentang masalah ini di CppCon 2016, yang dapat Anda lihat di YouTube: Kebocoran Kebebasan dalam C ++ ... Secara Default.
wiktor.wandachowicz
1
@ wiktor.wandachowicz T*adalah untuk std::unique_ptr<T>apa std::weak_ptr<T>adalah untukstd::shared_ptr<T>
Caleth
@ Caleth: Tidak, saya tidak akan mengatakan itu.
einpoklum
1
@TonyTannous: Dengan hormat - Itu adalah suntingan utama; dan saya tidak merasakan jawaban saya, yang abstrak, membutuhkannya. Saya sarankan Anda menjadikan contoh jawaban terpisah, di tautannya dalam komentar.
einpoklum
112

Smart pointer adalah tipe mirip-pointer dengan beberapa fungsi tambahan, misal penghentian memori otomatis, penghitungan referensi dll.

Intro kecil tersedia di halaman Smart Pointers - What, Why, Which? .

Salah satu tipe smart-pointer sederhana adalah std::auto_ptr(bab 20.4.5 dari standar C ++), yang memungkinkan untuk mendeallocate memori secara otomatis ketika berada di luar ruang lingkup dan yang lebih kuat daripada penggunaan pointer sederhana ketika pengecualian dilemparkan, meskipun kurang fleksibel.

Tipe nyaman lainnya adalah boost::shared_ptryang mengimplementasikan penghitungan referensi dan secara otomatis mendelokasi memori ketika tidak ada referensi ke objek. Ini membantu menghindari kebocoran memori dan mudah digunakan untuk mengimplementasikan RAII .

Subjek dibahas secara mendalam dalam buku "C ++ Templates: The Complete Guide" oleh David Vandevoorde, Nicolai M. Josuttis , bab Bab 20. Smart Pointers. Beberapa topik yang dibahas:

sergtk
sumber
2
Peringatan std::auto_ptrsudah usang dan sangat tidak disarankan karena Anda dapat secara tidak sengaja mentransfer kepemilikan. - C ++ 11 menghilangkan kebutuhan Boost, penggunaan: std::unique_ptr, std::shared_ptrdanstd::weak_ptr
ninMonkey
42

Definisi yang diberikan oleh Chris, Sergdev dan Llyod benar. Saya lebih suka definisi yang lebih sederhana, hanya untuk membuat hidup saya sederhana: Penunjuk pintar hanyalah sebuah kelas yang membebani -> dan *operator. Yang berarti bahwa objek Anda secara semantik terlihat seperti sebuah pointer tetapi Anda dapat membuatnya melakukan hal-hal yang lebih dingin, termasuk penghitungan referensi, penghancuran otomatis, dll. shared_ptrDan auto_ptrcukup dalam banyak kasus, tetapi datang bersama dengan seperangkat keanehan kecil mereka sendiri.

Sridhar Iyer
sumber
30

Pointer pintar seperti pointer biasa (diketik), seperti "char *", kecuali ketika pointer itu sendiri keluar dari ruang lingkup maka apa yang menunjuk ke dihapus juga. Anda dapat menggunakannya seperti menggunakan pointer biasa, dengan menggunakan "->", tetapi tidak jika Anda membutuhkan pointer aktual ke data. Untuk itu, Anda dapat menggunakan "& * ptr".

Ini berguna untuk:

  • Objek yang harus dialokasikan dengan yang baru, tetapi Anda ingin memiliki masa hidup yang sama dengan sesuatu di tumpukan itu. Jika objek ditugaskan ke penunjuk pintar, maka mereka akan dihapus ketika program keluar dari fungsi / blok itu.

  • Anggota data kelas, sehingga ketika objek dihapus semua data yang dimiliki juga dihapus, tanpa kode khusus di destructor (Anda harus memastikan destructor adalah virtual, yang hampir selalu merupakan hal yang baik untuk dilakukan) .

Anda mungkin tidak ingin menggunakan penunjuk pintar saat:

  • ... pointer seharusnya tidak benar-benar memiliki data ... yaitu, ketika Anda hanya menggunakan data, tetapi Anda ingin itu bertahan dari fungsi di mana Anda mereferensikannya.
  • ... smart pointer itu sendiri tidak akan dihancurkan di beberapa titik. Anda tidak ingin itu berada di memori yang tidak pernah dihancurkan (seperti pada objek yang dialokasikan secara dinamis tetapi tidak akan dihapus secara eksplisit).
  • ... dua pointer cerdas mungkin menunjuk ke data yang sama. (Namun, ada pointer lebih pintar yang akan menangani itu ... yang disebut penghitungan referensi .)

Lihat juga:

pasar
sumber
18

Kebanyakan jenis pointer pintar menangani membuang objek pointer-to untuk Anda. Ini sangat berguna karena Anda tidak perlu berpikir tentang membuang benda secara manual lagi.

Pointer pintar yang paling umum digunakan adalah std::tr1::shared_ptr (atau boost::shared_ptr), dan, lebih jarang std::auto_ptr,. Saya merekomendasikan penggunaan regulershared_ptr .

shared_ptrsangat fleksibel dan berhubungan dengan berbagai macam skenario pembuangan, termasuk kasus di mana objek perlu "melewati batas DLL" (kasus mimpi buruk umum jika berbeda libcdigunakan antara kode Anda dan DLL).

Chris Jester-Young
sumber
18

Smart pointer adalah objek yang bertindak seperti pointer, tetapi juga memberikan kontrol pada konstruksi, penghancuran, penyalinan, pemindahan, dan dereferencing.

Seseorang dapat mengimplementasikan smart pointer sendiri, tetapi banyak perpustakaan juga menyediakan implementasi smart pointer masing-masing dengan kelebihan dan kekurangan yang berbeda.

Misalnya, Boost menyediakan implementasi smart pointer berikut:

  • shared_ptr<T>adalah pointer untuk Tmenggunakan jumlah referensi untuk menentukan kapan objek tidak lagi dibutuhkan.
  • scoped_ptr<T>adalah pointer yang dihapus secara otomatis ketika keluar dari ruang lingkup. Tidak ada tugas yang memungkinkan.
  • intrusive_ptr<T>adalah pointer penghitung referensi lain. Ini memberikan kinerja yang lebih baik daripada shared_ptr, tetapi membutuhkan jenis Tuntuk menyediakan mekanisme penghitungan referensi sendiri.
  • weak_ptr<T>adalah penunjuk yang lemah, bekerja bersamaan dengan shared_ptruntuk menghindari referensi melingkar.
  • shared_array<T>seperti shared_ptr, tetapi untuk array T.
  • scoped_array<T>seperti scoped_ptr, tetapi untuk array T.

Ini hanya satu deskripsi linear dari masing-masing dan dapat digunakan sesuai kebutuhan, untuk detail lebih lanjut dan contoh orang dapat melihat dokumentasi Boost.

Selain itu, pustaka standar C ++ menyediakan tiga pointer cerdas; std::unique_ptruntuk kepemilikan yang unik, std::shared_ptruntuk kepemilikan bersama dan std::weak_ptr. std::auto_ptrada di C ++ 03 tetapi sekarang sudah usang.

Saqlain
sumber
Tolong jelaskan mengapa scoped_ptrtidak seperti yang dideklarasikan secara lokal const unique_ptr- yang juga dihapus saat keluar dari ruang lingkup.
einpoklum
11

Inilah Tautan untuk jawaban serupa: http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html

Pointer pintar adalah objek yang bertindak, terlihat dan terasa seperti pointer normal tetapi menawarkan lebih banyak fungsi. Di C ++, smart pointer diimplementasikan sebagai kelas templat yang merangkum sebuah pointer dan menimpa operator pointer standar. Mereka memiliki sejumlah keunggulan dibandingkan pointer biasa. Mereka dijamin diinisialisasi sebagai null pointer atau pointer ke objek tumpukan. Peniruan melalui pointer nol diperiksa. Tidak perlu menghapus. Objek secara otomatis dibebaskan ketika pointer terakhir ke mereka telah pergi. Satu masalah signifikan dengan pointer cerdas ini adalah bahwa tidak seperti pointer biasa, mereka tidak menghormati warisan. Pointer pintar tidak menarik untuk kode polimorfik. Diberikan di bawah ini adalah contoh untuk penerapan smart pointer.

Contoh:

template <class X>
class smart_pointer
{
          public:
               smart_pointer();                          // makes a null pointer
               smart_pointer(const X& x)            // makes pointer to copy of x

               X& operator *( );
               const X& operator*( ) const;
               X* operator->() const;

               smart_pointer(const smart_pointer <X> &);
               const smart_pointer <X> & operator =(const smart_pointer<X>&);
               ~smart_pointer();
          private:
               //...
};

Kelas ini menerapkan pointer pintar ke objek tipe X. Objek itu sendiri terletak di heap. Berikut cara menggunakannya:

smart_pointer <employee> p= employee("Harris",1333);

Seperti operator kelebihan beban lainnya, p akan berperilaku seperti pointer biasa,

cout<<*p;
p->raise_salary(0.5);
Santosh
sumber
9

http://en.wikipedia.org/wiki/Smart_pointer

Dalam ilmu komputer, penunjuk cerdas adalah tipe data abstrak yang mensimulasikan penunjuk sambil memberikan fitur tambahan, seperti pengumpulan sampah otomatis atau pemeriksaan batas. Fitur tambahan ini dimaksudkan untuk mengurangi bug yang disebabkan oleh penyalahgunaan pointer sambil mempertahankan efisiensi. Pointer pintar biasanya melacak objek yang menunjuk mereka untuk tujuan manajemen memori. Penyalahgunaan pointer adalah sumber utama bug: alokasi konstan, deallokasi dan referensi yang harus dilakukan oleh program yang ditulis menggunakan pointer membuatnya sangat mungkin bahwa beberapa kebocoran memori akan terjadi. Pointer pintar mencoba untuk mencegah kebocoran memori dengan membuat sumber daya otomatis: ketika pointer ke objek (atau yang terakhir dalam serangkaian pointer) dihancurkan,

Jorge Ferreira
sumber
6

Biarkan T menjadi kelas dalam tutorial ini. Petunjuk dalam C ++ dapat dibagi menjadi 3 jenis:

1) Petunjuk mentah :

T a;  
T * _ptr = &a; 

Mereka memegang alamat memori ke lokasi di memori. Gunakan dengan hati-hati, karena program menjadi rumit sulit untuk dilacak.

Pointer dengan data atau alamat const {Baca mundur}

T a ; 
const T * ptr1 = &a ; 
T const * ptr1 = &a ;

Pointer ke tipe data T yang merupakan const. Berarti Anda tidak dapat mengubah tipe data menggunakan pointer. yaitu *ptr1 = 19; tidak akan bekerja. Tapi Anda bisa memindahkan pointer. yaitu ptr1++ , ptr1--; dll akan bekerja. Baca mundur: pointer ke tipe T yang merupakan const

  T * const ptr2 ;

Pointer const ke tipe data T. Berarti Anda tidak dapat memindahkan pointer tetapi Anda dapat mengubah nilai yang ditunjuk oleh pointer. yaitu *ptr2 = 19akan bekerja tetapi ptr2++ ; ptr2--dll tidak akan bekerja. Baca mundur: pointer pointer ke tipe T

const T * const ptr3 ; 

Pointer const ke tipe data const T. Berarti Anda tidak bisa menggerakkan pointer juga tidak bisa mengubah pointer tipe data menjadi pointer. yaitu. ptr3-- ; ptr3++ ; *ptr3 = 19;tidak akan bekerja

3) Smart Pointers : { #include <memory>}

Pointer Bersama :

  T a ; 
     //shared_ptr<T> shptr(new T) ; not recommended but works 
     shared_ptr<T> shptr = make_shared<T>(); // faster + exception safe

     std::cout << shptr.use_count() ; // 1 //  gives the number of " 
things " pointing to it. 
     T * temp = shptr.get(); // gives a pointer to object

     // shared_pointer used like a regular pointer to call member functions
      shptr->memFn();
     (*shptr).memFn(); 

    //
     shptr.reset() ; // frees the object pointed to be the ptr 
     shptr = nullptr ; // frees the object 
     shptr = make_shared<T>() ; // frees the original object and points to new object

Diimplementasikan menggunakan penghitungan referensi untuk melacak berapa banyak "hal" menunjuk ke objek yang ditunjuk oleh pointer. Ketika jumlah ini masuk ke 0, objek dihapus secara otomatis, yaitu keberatan dihapus ketika semua share_ptr yang menunjuk ke objek keluar dari ruang lingkup. Ini menghilangkan sakit kepala karena harus menghapus objek yang telah Anda alokasikan menggunakan yang baru.

Weak Pointer: Membantu menangani referensi siklik yang muncul saat menggunakan Shared Pointer Jika Anda memiliki dua objek yang ditunjuk oleh dua pointer bersama dan ada internal pointer bersama menunjuk satu sama lain bersama pointer maka akan ada referensi siklik dan objek tidak akan dihapus ketika pointer bersama keluar dari ruang lingkup. Untuk mengatasi ini, ubah anggota internal dari shared_ptr menjadi kelemahan_ptr. Catatan: Untuk mengakses elemen yang ditunjuk oleh penunjuk lemah gunakan kunci (), ini mengembalikan melemah_ptr.

T a ; 
shared_ptr<T> shr = make_shared<T>() ; 
weak_ptr<T> wk = shr ; // initialize a weak_ptr from a shared_ptr 
wk.lock()->memFn() ; // use lock to get a shared_ptr 
//   ^^^ Can lead to exception if the shared ptr has gone out of scope
if(!wk.expired()) wk.lock()->memFn() ;
// Check if shared ptr has gone out of scope before access

Lihat: Kapan std :: lemah_ptr berguna?

Pointer Unik: Pointer pintar ringan dengan kepemilikan eksklusif. Gunakan saat penunjuk menunjuk ke objek unik tanpa berbagi objek di antara pointer.

unique_ptr<T> uptr(new T);
uptr->memFn(); 

//T * ptr = uptr.release(); // uptr becomes null and object is pointed to by ptr
uptr.reset() ; // deletes the object pointed to by uptr 

Untuk mengubah objek yang ditunjuk oleh ptr unik, gunakan pindahkan semantik

unique_ptr<T> uptr1(new T);
unique_ptr<T> uptr2(new T);
uptr2 = std::move(uptr1); 
// object pointed by uptr2 is deleted and 
// object pointed by uptr1 is pointed to by uptr2
// uptr1 becomes null 

Referensi: Mereka pada dasarnya dapat dianggap sebagai const pointer, yaitu pointer yang merupakan const dan tidak dapat dipindahkan dengan sintaks yang lebih baik.

Lihat: Apa perbedaan antara variabel penunjuk dan variabel referensi dalam C ++?

r-value reference : reference to a temporary object   
l-value reference : reference to an object whose address can be obtained
const reference : reference to a data type which is const and cannot be modified 

Referensi: https://www.youtube.com/channel/UCEOGtxYTB6vo6MQ-WQ9W_nQ Terima kasih kepada Andre yang telah menunjukkan pertanyaan ini.

nnrales
sumber
3

Pointer pintar adalah kelas, pembungkus pointer normal. Tidak seperti pointer normal, lingkaran kehidupan titik pintar didasarkan pada jumlah referensi (berapa kali objek penunjuk pintar ditugaskan). Jadi, setiap kali pointer cerdas ditugaskan ke yang lain, referensi internal akan menghitung plus plus. Dan setiap kali objek keluar dari ruang lingkup, jumlah referensi dikurangi minus.

Pointer otomatis, meskipun terlihat serupa, sama sekali berbeda dari smart pointer. Ini adalah kelas yang mudah digunakan yang tidak menggunakan sumber daya kapan pun objek pointer otomatis keluar dari ruang lingkup variabel. Sampai batas tertentu, itu membuat pointer (ke memori yang dialokasikan secara dinamis) bekerja mirip dengan variabel stack (dialokasikan secara statis dalam waktu kompilasi).

Trombe
sumber
2

Smart Pointer adalah di mana Anda tidak perlu khawatir tentang De-Alokasi Memori, Berbagi Sumber Daya, dan Transfer.

Anda dapat menggunakan pointer ini dengan sangat baik dengan cara yang sama seperti alokasi bekerja di Jawa. Di java Sampah Kolektor melakukan trik, sedangkan di Smart Pointers, trik tersebut dilakukan oleh Destructors.

Daksh
sumber
1

Jawaban yang ada bagus tetapi tidak mencakup apa yang harus dilakukan ketika smart pointer bukan jawaban (lengkap) untuk masalah yang Anda coba selesaikan.

Antara lain (dijelaskan dengan baik dalam jawaban lain) menggunakan smart pointer adalah solusi yang memungkinkan untuk Bagaimana kita menggunakan kelas abstrak sebagai tipe fungsi kembali? yang telah ditandai sebagai duplikat dari pertanyaan ini. Namun, pertanyaan pertama yang ditanyakan apakah tergoda untuk menentukan kelas dasar abstrak (atau bahkan, ada) sebagai tipe pengembalian dalam C ++ adalah "apa maksudmu sebenarnya?". Ada diskusi yang baik (dengan referensi lebih lanjut) pemrograman berorientasi objek idiomatik dalam C ++ (dan bagaimana hal ini berbeda dengan bahasa lain) dalam dokumentasi perpustakaan penambah penunjuk arah. Singkatnya, di C ++ Anda harus memikirkan kepemilikan. Pointer pintar mana yang membantu Anda, tetapi bukan satu-satunya solusi, atau selalu merupakan solusi lengkap (mereka tidak memberi Anda salinan polimorfik) dan tidak selalu merupakan solusi yang ingin Anda paparkan di antarmuka Anda (dan pengembalian fungsi terdengar mengerikan. banyak seperti antarmuka). Mungkin cukup untuk mengembalikan referensi, misalnya. Tetapi dalam semua kasus ini (penunjuk pintar, penunjuk wadah atau hanya mengembalikan referensi) Anda telah mengubah pengembalian dari nilai ke beberapa bentuk referensi . Jika Anda benar-benar perlu menyalin, Anda mungkin perlu menambahkan "idiom" boilerplate atau beralih melampaui OO idiomatik (atau sebaliknya) di C ++ ke polimorfisme yang lebih umum menggunakan perpustakaan seperti Adobe Poly atau Boost.TypeErasure.

da77a
sumber