Pertanyaan Apa itu penunjuk pintar dan kapan saya harus menggunakannya?


Apa itu penunjuk pintar dan kapan saya harus menggunakannya?


1427
2017-09-20 00:09


asal


Jawaban:


Penunjuk pintar adalah kelas yang membungkus pointer C ++ 'mentah' (atau 'telanjang'), untuk mengatur umur objek yang diarahkan. Tidak ada satu pun tipe pointer pintar, tetapi semuanya mencoba untuk mengabstrakkan pointer mentah dengan cara yang praktis.

Smart pointer harus lebih disukai daripada pointer mentah. Jika Anda merasa perlu menggunakan pointer (pertama pertimbangkan jika Anda sangat lakukan), Anda biasanya ingin menggunakan pointer pintar karena ini dapat meringankan banyak masalah dengan pointer mentah, terutama lupa untuk menghapus objek dan membocorkan memori.

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

Penunjuk pintar dengan perbandingan mendefinisikan kebijakan tentang kapan objek tersebut dihancurkan. Anda masih harus membuat objek, tetapi Anda tidak perlu khawatir akan merusaknya.

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 lingkup objek pembungkus pointer pintar, seperti yang diterapkan oleh boost::scoped_ptr atau std::unique_ptr.

void f()
{
    {
       boost::scoped_ptr<MyObject> ptr(new MyObject());
       ptr->DoSomethingUseful();
    } // boost::scopted_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 itu scoped_ptr contoh tidak dapat disalin. Ini mencegah penunjuk dihapus beberapa kali (salah). Anda bisa, bagaimanapun, memberikan referensi ke sekitar untuk fungsi-fungsi lain yang Anda panggil.

Scoped pointer berguna ketika Anda ingin mengikat umur objek ke blok kode tertentu, atau jika Anda menyematkannya sebagai data anggota di dalam objek lain, masa pakai objek lain tersebut. Objek itu ada sampai blok kode yang berisi dikeluarkan, atau sampai objek yang berisi itu sendiri dihancurkan.

Kebijakan penunjuk pintar yang lebih kompleks melibatkan referensi yang menghitung penunjuk. Ini memungkinkan penunjuk untuk disalin. Ketika "referensi" terakhir ke objek dihancurkan, objek dihapus. Kebijakan ini diterapkan oleh boost::shared_ptr dan 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 menghitung pointer sangat berguna ketika masa hidup objek Anda jauh lebih rumit, dan tidak terikat langsung ke bagian kode tertentu atau ke objek lain.

Ada satu kelemahan untuk referensi pointer dihitung - kemungkinan menciptakan referensi 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 menciptakan referensi melingkar:

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

boost::shared_ptr<Owner> p1 (new Owner());
boost::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, baik Boost dan C ++ 11 telah mendefinisikan a weak_ptr untuk menentukan referensi yang lemah (tidak terhitung) ke a shared_ptr.


MEMPERBARUI

Jawaban ini agak lama, dan menggambarkan apa yang 'bagus' pada saat itu, yang merupakan petunjuk cerdas yang disediakan oleh perpustakaan Boost. Karena C ++ 11, pustaka standar telah menyediakan jenis pointer pintar yang cukup, sehingga Anda harus mendukung penggunaan std::unique_ptr, std::shared_ptr dan std::weak_ptr.

Ada juga std::auto_ptr. Ini sangat mirip dengan pointer scoped, kecuali bahwa itu juga memiliki kemampuan berbahaya "khusus" untuk disalin - yang juga secara tidak terduga mentransfer kepemilikan! Ini sudah usang dalam standar terbaru, jadi Anda tidak boleh menggunakannya. Menggunakan std::unique_ptr sebagai gantinya.

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.

1640
2017-09-20 00:48



Berikut ini adalah jawaban sederhana untuk hari-hari modern C ++ ini:

  • Apa itu penunjuk pintar? 
    Ini adalah jenis nilai yang dapat digunakan seperti penunjuk, tetapi menyediakan fitur tambahan dari manajemen memori otomatis: Ketika penunjuk tidak lagi digunakan, memori yang dikodekannya akan dinonaktifkan (lihat juga definisi yang lebih rinci di Wikipedia).
  • Kapan saya harus menggunakannya? 
    Dalam kode yang melibatkan pelacakan kepemilikan sepotong memori, mengalokasikan atau mendelegasikan; pointer pintar sering menghemat kebutuhan untuk melakukan hal-hal ini secara eksplisit.
  • Tetapi pointer cerdas mana yang harus saya gunakan untuk kasus-kasus tersebut?
    • Menggunakan std::unique_ptr ketika Anda tidak berniat untuk memegang beberapa referensi ke objek yang sama. Sebagai contoh, gunakan untuk pointer ke memori yang dialokasikan untuk memasuki beberapa ruang lingkup dan tidak dialokasikan saat keluar dari ruang lingkup.
    • Menggunakan std::shared_ptr ketika Anda ingin merujuk ke objek Anda dari beberapa tempat - dan tidak ingin itu tidak dialokasikan sampai semua referensi ini hilang.
    • Menggunakan std::weak_ptr ketika Anda ingin merujuk ke objek Anda dari beberapa tempat - untuk referensi yang ok untuk mengabaikan dan deallocate (sehingga mereka hanya akan mencatat objek hilang ketika Anda mencoba untuk dereference).
    • Jangan gunakan boost:: pointer pintar atau std::auto_ptr kecuali dalam kasus-kasus khusus yang dapat Anda baca jika Anda harus.
  • Hei, aku tidak bertanya yang mana yang akan digunakan! 
    Ah, tetapi Anda benar-benar ingin, mengakuinya.
  • Jadi kapan saya harus menggunakan pointer biasa? 
    Sebagian besar dalam kode yang tidak memperhatikan kepemilikan memori. Ini biasanya berada dalam fungsi yang mendapatkan penunjuk dari tempat lain dan tidak mengalokasikan, tidak mengalokasikan atau menyimpan salinan penunjuk yang melebihi eksekusinya.

170
2018-05-09 19:06



Penunjuk pintar adalah jenis penunjuk seperti dengan beberapa fungsi tambahan, mis. deallokasi memori otomatis, penghitungan referensi dll.

Pengantar kecil tersedia di halaman Smart Pointer - Apa, Mengapa, Mana?.

Salah satu tipe smart-pointer sederhana adalah std::auto_ptr (Bab 20.4.5 standar C ++), yang memungkinkan untuk mengalihkan memori secara otomatis ketika keluar dari ruang lingkup dan yang lebih kuat dari penggunaan penunjuk sederhana ketika pengecualian dilemparkan, meskipun kurang fleksibel.

Tipe nyaman lainnya adalah boost::shared_ptr yang mengimplementasikan penghitungan referensi dan secara otomatis mengalihkan memori ketika tidak ada referensi ke objek yang tersisa. Ini membantu menghindari kebocoran memori dan mudah digunakan untuk diterapkan RAII.

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


96
2017-09-20 00:32



Definisi yang diberikan oleh Chris, Sergdev dan Llyod benar. Saya lebih suka definisi yang lebih sederhana, hanya untuk menjaga hidup saya sederhana: Penunjuk pintar hanyalah sebuah kelas yang terlalu banyak ->dan * operator. Yang berarti objek Anda secara semantis terlihat seperti pointer tetapi Anda dapat membuatnya melakukan hal-hal yang lebih dingin, termasuk penghitungan referensi, penghancuran otomatis, dll. shared_ptr dan auto_ptr cukup dalam banyak kasus, tetapi datang dengan seperangkat idiosinkrasi kecil mereka sendiri.


33
2017-09-20 01:53



Penunjuk pintar seperti penunjuk biasa (diketik), seperti "char *", kecuali ketika penunjuk itu sendiri keluar dari ruang lingkup maka apa yang ditunjuknya juga dihapus. Anda dapat menggunakannya seperti Anda menggunakan penunjuk biasa, dengan menggunakan "->", tetapi tidak jika Anda membutuhkan penunjuk yang sebenarnya ke data. Untuk itu, Anda bisa 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 pointer pintar, maka mereka akan dihapus ketika program keluar dari fungsi / blok tersebut.

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

Kamu boleh tidak ingin menggunakan penunjuk pintar saat:

  • ... penunjuk tidak seharusnya benar-benar memiliki data ... yaitu, ketika Anda hanya menggunakan data, tetapi Anda ingin itu bertahan dari fungsi di mana Anda mereferensikannya.
  • ... Penunjuk pintar itu sendiri tidak akan hancur di beberapa titik. Anda tidak ingin duduk di memori yang tidak pernah hancur (seperti dalam objek yang dialokasikan secara dinamis tetapi tidak akan secara eksplisit dihapus).
  • ... dua petunjuk cerdas mungkin menunjuk ke data yang sama. (Namun demikian, bahkan pointer lebih pintar yang akan menangani itu ... itulah yang disebut penghitungan referensi.)

Lihat juga:


26
2017-09-20 00:13



Sebagian besar jenis pointer pintar menangani membuang pointer-ke objek untuk Anda. Ini sangat berguna karena Anda tidak perlu memikirkan membuang benda secara manual lagi.

Pointer cerdas yang paling sering digunakan adalah std::tr1::shared_ptr (atau boost::shared_ptr), dan, lebih jarang, std::auto_ptr. Saya merekomendasikan penggunaan reguler shared_ptr.

shared_ptr sangat serbaguna dan berhubungan dengan berbagai macam skenario pembuangan, termasuk kasus di mana benda-benda harus "dilewatkan melintasi batas-batas DLL" (kasus mimpi buruk umum jika berbeda libcs digunakan antara kode Anda dan DLL).


14
2017-09-20 00:14



Penunjuk pintar adalah objek yang bertindak seperti penunjuk, tetapi juga menyediakan kontrol pada konstruksi, perusakan, penyalinan, pemindahan, dan dereferensi.

Satu dapat mengimplementasikan pointer pintar sendiri, tetapi banyak pustaka juga menyediakan penerapan pointer pintar masing-masing dengan kelebihan dan kekurangan yang berbeda.

Sebagai contoh, Dorongan menyediakan implementasi penunjuk pintar berikut:

  • shared_ptr<T> adalah penunjuk ke T menggunakan jumlah referensi untuk menentukan kapan objek tidak lagi diperlukan.
  • scoped_ptr<T> adalah penunjuk yang dihapus secara otomatis ketika keluar dari ruang lingkup. Tidak ada tugas yang memungkinkan.
  • intrusive_ptr<T>adalah pointer penghitung referensi lainnya. Ini memberikan kinerja yang lebih baik daripada shared_ptr, tetapi membutuhkan tipe T untuk menyediakan mekanisme penghitungan referensi sendiri.
  • weak_ptr<T> adalah penunjuk yang lemah, bekerja bersama shared_ptr untuk 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 linier masing-masing dan dapat digunakan sesuai kebutuhan, untuk detail lebih lanjut dan contoh yang dapat dilihat pada dokumentasi Boost.

Selain itu, pustaka standar C ++ menyediakan tiga pointer pintar; std::unique_ptr untuk kepemilikan unik, std::shared_ptr untuk kepemilikan bersama dan std::weak_ptr. std::auto_ptr ada di C ++ 03 tetapi sekarang tidak lagi digunakan.


14
2018-03-12 09:51



Berikut ini tautan untuk jawaban yang serupa: http://situsprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html

Penunjuk pintar adalah objek yang bertindak, terlihat, dan terasa seperti penunjuk normal tetapi menawarkan lebih banyak fungsi. Dalam C ++, pointer cerdas diimplementasikan sebagai kelas template yang mengenkapsulasi pointer dan mengesampingkan operator penunjuk standar. Mereka memiliki sejumlah keunggulan dibandingkan pointer reguler. Mereka dijamin akan diinisialisasi sebagai null pointer atau pointer ke objek heap. Indireksi melalui pointer null dicentang. Tidak perlu menghapus. Objek secara otomatis dibebaskan ketika penunjuk terakhir ke mereka telah pergi. Satu masalah signifikan dengan pointer pintar ini adalah bahwa tidak seperti pointer biasa, mereka tidak menghargai warisan. Smart pointer tidak menarik untuk kode polimorfik. Diberikan di bawah ini adalah contoh untuk penerapan pointer pintar.

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 mengimplementasikan pointer pintar ke objek tipe X. Objek itu sendiri terletak di heap. Berikut ini cara menggunakannya:

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

Seperti operator yang kelebihan beban lainnya, p akan berperilaku seperti penunjuk biasa,

cout<<*p;
p->raise_salary(0.5);

9
2018-03-07 09:03



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

Dalam ilmu komputer, pointer pintar   adalah tipe data abstrak itu   mensimulasikan pointer sambil menyediakan   fitur tambahan, seperti otomatis   pengumpulan sampah atau pemeriksaan batas.   Fitur tambahan ini dimaksudkan   untuk mengurangi bug yang disebabkan oleh penyalahgunaan   pointer sambil mempertahankan efisiensi.   Smart pointer biasanya melacak   objek yang mengarah ke mereka untuk   tujuan manajemen memori. Itu   penyalahgunaan pointer merupakan sumber utama   bug: alokasi konstan,   dealokasi dan referensi yang harus   dilakukan oleh program yang ditulis   menggunakan pointer membuatnya sangat mungkin   bahwa beberapa kebocoran memori akan terjadi.   Petunjuk cerdas mencoba mencegah memori   kebocoran dengan membuat sumber daya   dealokasi otomatis: ketika   penunjuk ke objek (atau yang terakhir dalam   serangkaian pointer) dihancurkan, untuk   Misalnya karena keluar dari ruang lingkup,   benda runcing juga hancur.


8
2017-09-20 00:12