Saya mencoba memahami cara std::unique_ptr
kerjanya dan untuk itu saya menemukan dokumen ini . Penulis memulai dari contoh berikut:
#include <utility> //declarations of unique_ptr
using std::unique_ptr;
// default construction
unique_ptr<int> up; //creates an empty object
// initialize with an argument
unique_ptr<int> uptr (new int(3));
double *pd= new double;
unique_ptr<double> uptr2 (pd);
// overloaded * and ->
*uptr2 = 23.5;
unique_ptr<std::string> ups (new std::string("hello"));
int len=ups->size();
Yang membingungkan saya adalah di baris ini
unique_ptr<int> uptr (new int(3));
Kami menggunakan integer sebagai argumen (antara tanda kurung siku) dan di sini
unique_ptr<double> uptr2 (pd);
kami menggunakan pointer sebagai argumen. Apakah ada bedanya?
Yang juga tidak jelas bagi saya, adalah bagaimana pointer yang dinyatakan dengan cara ini akan berbeda dari pointer yang dinyatakan dengan cara yang "normal".
c++
pointers
std
unique-ptr
Roma
sumber
sumber
new int(3)
mengembalikan sebuah penunjuk ke yang baruint
, sepertipd
penunjuk ke yang barudouble
.Jawaban:
Konstruktor
unique_ptr<T>
menerima penunjuk mentah ke objek bertipeT
(jadi, ia menerima aT*
).Pada contoh pertama:
unique_ptr<int> uptr (new int(3));
Pointer adalah hasil
new
ekspresi, sedangkan pada contoh kedua:unique_ptr<double> uptr2 (pd);
Penunjuk disimpan dalam
pd
variabel.Secara konseptual, tidak ada yang berubah (Anda membuat a
unique_ptr
dari pointer mentah), tetapi pendekatan kedua berpotensi lebih berbahaya, karena akan memungkinkan Anda, misalnya, untuk melakukan:unique_ptr<double> uptr2 (pd); // ... unique_ptr<double> uptr3 (pd);
Dengan demikian memiliki dua penunjuk unik yang secara efektif merangkum objek yang sama (sehingga melanggar semantik penunjuk unik ).
Inilah mengapa formulir pertama untuk membuat penunjuk unik lebih baik, jika memungkinkan. Perhatikan, bahwa dalam C ++ 14 kita dapat melakukan:
unique_ptr<int> p = make_unique<int>(42);
Yang mana lebih jelas dan lebih aman. Sekarang tentang keraguan Anda ini:
Pointer cerdas seharusnya memodelkan kepemilikan objek, dan secara otomatis menangani pemusnahan objek yang diarahkan saat pointer terakhir (cerdas, memiliki) ke objek tersebut berada di luar cakupan.
Dengan cara ini Anda tidak perlu mengingat melakukannya
delete
pada objek yang dialokasikan secara dinamis - destruktor dari smart pointer akan melakukannya untuk Anda - atau khawatir tentang apakah Anda tidak akan membatalkan pointer (menggantung) ke objek yang sudah dihancurkan:{ unique_ptr<int> p = make_unique<int>(42); // Going out of scope... } // I did not leak my integer here! The destructor of unique_ptr called delete
Sekarang
unique_ptr
adalah penunjuk cerdas yang memodelkan kepemilikan unik, yang berarti bahwa setiap saat dalam program Anda hanya akan ada satu penunjuk (yang memiliki) ke objek yang diarahkan - itulah mengapaunique_ptr
tidak dapat disalin.Selama Anda menggunakan petunjuk cerdas dengan cara yang tidak melanggar kontrak implisit yang harus Anda patuhi, Anda akan mendapat jaminan bahwa tidak ada memori yang bocor, dan kebijakan kepemilikan yang tepat untuk objek Anda akan diberlakukan. Petunjuk mentah tidak memberi Anda jaminan ini.
sumber
model object ownership
,integer leak
dalam kode atauenforcing ownership policy for object
. Bisakah Anda menyarankan topik / sumber daya untuk mempelajari konsep ini?unique_ptr
, tanpa mendapatkan kesalahanThe text ">" is unexpected. It may be that this token was intended as a template argument list terminator but the name is not known to be a template.
:, meskipun saya memiliki#include <utility>
dan#include <memory>
. Ada saran?Tidak ada perbedaan dalam mengerjakan kedua konsep penugasan ke unique_ptr.
int* intPtr = new int(3); unique_ptr<int> uptr (intPtr);
mirip dengan
unique_ptr<int> uptr (new int(3));
Di sini unique_ptr secara otomatis menghapus ruang yang ditempati
uptr
.Jika Anda membuat integer di ruang heap (menggunakan kata kunci baru atau malloc ), maka Anda harus membersihkan memori itu sendiri ( masing-masing menggunakan delete atau free ).
Pada kode di bawah ini,
int* heapInt = new int(5);//initialize int in heap memory . .//use heapInt . delete heapInt;
Di sini, Anda harus menghapus heapInt, jika sudah selesai menggunakan. Jika tidak dihapus, maka terjadi kebocoran memori.
Untuk menghindari kebocoran memori seperti itu unique_ptr digunakan, di mana unique_ptr secara otomatis menghapus ruang yang ditempati oleh heapInt saat keluar dari ruang lingkup. Jadi, Anda tidak perlu menghapus atau gratis untuk unique_ptr.
sumber
Pointer unik dijamin akan menghancurkan objek yang mereka kelola saat berada di luar jangkauan. http://en.cppreference.com/w/cpp/memory/unique_ptr
Pada kasus ini:
unique_ptr<double> uptr2 (pd);
pd
akan hancur saatuptr2
keluar dari ruang lingkup. Ini memfasilitasi manajemen memori dengan penghapusan otomatis.Kasusnya
unique_ptr<int> uptr (new int(3));
tidak berbeda, kecuali bahwa pointer mentah tidak ditugaskan ke variabel apa pun di sini.sumber
Dari cppreference , salah satu
std::unique_ptr
konstruktornya adalahunique_ptr eksplisit (pointer p) noexcept;
Jadi untuk membuat baru
std::unique_ptr
adalah meneruskan pointer ke konstruktornya.unique_ptr<int> uptr (new int(3));
Atau sama dengan
int *int_ptr = new int(3); std::unique_ptr<int> uptr (int_ptr);
Bedanya, Anda tidak perlu membersihkan setelah menggunakannya. Jika Anda tidak menggunakan
std::unique_ptr
(penunjuk cerdas), Anda harus menghapusnya seperti inidelete int_ptr;
ketika Anda tidak lagi membutuhkannya atau itu akan menyebabkan kebocoran memori.
sumber