Pasti memberi +1 pada ini karena saya telah melihat begitu banyak orang yang salah. Ini pertanyaan yang bagus untuk ditanyakan.
twokats
Baca juga item terkait. Pertanyaan ini dipertimbangkan di sini dari sisi lain. Semoga bermanfaat untuk memahami lebih lanjut tentang auto_ptr dan wadah STL. stackoverflow.com/questions/8630552/…
movesemantik dan unique_ptrdirancang untuk menghindari masalah yang berkaitan dengan auto_ptr. Di C ++ 03, bahasa tidak cukup kuat untuk menulis kelas seperti auto_ptritu berperilaku dengan benar dan aman di semua skenario karena kompilator dan bahasa tidak dapat membedakan nilai l dan r sehingga beberapa "peretasan" digunakan untuk mendapatkan perilaku yang diinginkan sebagian besar waktu.
Phil1970
Artikel yang bagus: Wadah STL dan Auto_ptrs - Mengapa Mereka Tidak Mencampur quantstart.com/articles/…
alfC
Jawaban:
124
Standar C ++ mengatakan bahwa elemen STL harus "copy-constructible" dan "assignable." Dengan kata lain, suatu elemen harus dapat ditugaskan atau disalin dan kedua elemen tersebut secara logis independen. std::auto_ptrtidak memenuhi persyaratan ini.
Ambil contoh kode ini:
class X
{};
std::vector<std::auto_ptr<X>> vecX;
vecX.push_back(new X);
std::auto_ptr<X> pX = vecX[0];// vecX[0] is assigned NULL.
Anda juga harus mempertimbangkan wadah penunjuk boost, jika Anda tidak memerlukan kepemilikan bersama.
me22
4
unique_ptrjuga melarang penyalinan, sehingga operasi STL tertentu tidak akan berfungsi dengan benar kecuali mereka dapat menggunakan semantik gerakannya.
Mike Weller
4
"Untuk mengatasi batasan ini, Anda harus menggunakan std::unique_ptr": bahwa templat kelas hanya bisa ada karena memindahkan semantik (spesifikasinya memerlukan referensi nilai ulang), sehingga pada dasarnya memerlukan C ++ 11. Namun (dan terkait) Standar C ++ 11 tidak lagi mengatakan bahwa tipe elemen STL harus "copy-constructible" dan "assignable"; cukup bergerak-konstruktif dan bergerak-ditugaskan. Memang unique_ptrcontoh hanya bergerak-membangun dan memindahkan-ditugaskan. Tapi begitu juga auto_ptrcontoh! Sebagai konsekuensinya, dalam C ++ 11 Anda dapat melakukan auto_ptrapa yang dapat Anda lakukan unique_ptr.
Marc van Leeuwen
@MarcvanLeeuwen kecuali Anda resetdan releasejika diperlukan
ratchet freak
2
@ scratchetfreak: Hmm, saya tidak mengerti. Apa? "kecuali Anda resetdan release", saya tidak melihat bagaimana itu berlaku untuk apa pun dalam komentar saya. Perhatikan bahwa keduanya auto_ptrdan unique_ptrkedua metode ini, dan mereka melakukan hal yang sama dalam kedua kasus.
Marc van Leeuwen
66
The semantik copy dari auto_ptrtidak kompatibel dengan kontainer.
Secara khusus, menyalin satu auto_ptrke yang lain tidak membuat dua objek yang sama karena satu telah kehilangan kepemilikan pointer.
Lebih khusus lagi, menyalin auto_ptrpenyebab salah satu salinan untuk melepaskan pointer. Yang mana dari sisa-sisa ini dalam wadah tidak ditentukan. Oleh karena itu, Anda dapat kehilangan akses ke pointer secara acak jika Anda menyimpannya auto_ptrsdi dalam wadah.
Karena saya pikir dalam hampir dua tahun, dia mungkin menangani masalah yang ada.
Anak anjing
27
@DeadMG: ya, Anda benar. Tapi itu bukan tujuan saya. Jika seseorang datang ke utas ini kapan-kapan dan ingin belajar tentang sesuatu auto_ptr, tautan ini akan sangat membantu, saya yakin.
Lazer
Ada banyak duplikat yang lebih baru.
Puppy
8
@DeadMG: Pertanyaan ini tidak ditutup sebagai duplikat dan karenanya terbuka untuk ekstensi. Lazer mengatakan apa yang tidak dikatakan sebelumnya di sini. Saya kira dia datang secara kebetulan.
Sebastian Mach
Penjelasan dalam tautan kedua, yang menganalisis masalah setelah menelepon sort(), lebih jelas daripada semua jawaban di sini.
chaosink
17
Wadah STL harus dapat menyalin item yang Anda simpan di dalamnya, dan dirancang untuk mengharapkan yang asli dan salinannya setara. objek penunjuk otomatis memiliki kontrak yang sama sekali berbeda, di mana penyalinan membuat transfer kepemilikan. Ini berarti bahwa kontainer auto_ptr akan memperlihatkan perilaku aneh, tergantung penggunaan.
Ada uraian terperinci tentang apa yang salah dalam Efektif STL (Scott Meyers) item 8 dan juga deskripsi yang tidak terlalu terperinci dalam Efektif C ++ (Scott Meyers) item 13.
Wadah STL menyimpan salinan barang-barang yang terkandung. Ketika auto_ptr disalin, itu menetapkan ptr lama ke nol. Banyak metode wadah rusak oleh perilaku ini.
Tetapi, ketika menggunakan unique_ptr Anda mendapatkan hal yang hampir sama karena hanya satu unique_ptr yang dapat memiliki kepemilikan objek?
Tracer
2
@ Tracer unique_ptrseperti objek C ++ 11 yang tepat hanya dapat mentransfer kepemilikan sumber dayanya ketika dipindah-bangun atau-ditugaskan, memastikan bahwa pemrogram harus dengan sengaja melewati suatu std::move(sourceObject)atau sementara, alih-alih memberikan nilai dan secara tidak sengaja / tidak terduga dimutasi oleh copy-tugas ... yang, seperti ditekankan secara menyeluruh di sini, adalah masalah inti auto_ptr.
underscore_d
4
C ++ 03 Standar (ISO-IEC 14882-2003) mengatakan dalam klausa 20.4.5 paragraf 3:
[...] [ Catatan: [...] auto_ptr tidak memenuhi persyaratan CopyConstructible dan Assignable untuk elemen kontainer Perpustakaan Standar dan dengan demikian instantiate kontainer Perpustakaan Standar dengan hasil auto_ptr dalam perilaku yang tidak ditentukan. - catatan akhir ]
Standar C ++ 11 (ISO-IEC 14882-2011) mengatakan dalam lampiran D.10.1 paragraf 3:
[...]
Catatan: [...] Contoh auto_ptr memenuhi persyaratan MoveConstructible dan MoveAssignable, tetapi tidak memenuhi persyaratan CopyConstructible dan CopyAssignable. - catatan akhir]
Standar C ++ 14 (ISO-IEC 14882-2014) mengatakan dalam lampiran C.4.2 Lampiran D: fitur kompatibilitas:
Ubah : Templat kelas auto_ptr, unary_function, dan binary_function, templat fungsi random_shuffle, dan templat fungsi (dan tipe kembalinya) ptr_fun, mem_fun, mem_fun_ref, bind1st, dan bind2nd tidak didefinisikan. Dasar Pemikiran : Digantikan oleh fitur-fitur baru. Efek pada fitur asli : Kode C ++ 2014 yang valid yang menggunakan templat kelas dan templat fungsi ini mungkin gagal dikompilasi dalam Standar Internasional ini.
move
semantik danunique_ptr
dirancang untuk menghindari masalah yang berkaitan denganauto_ptr
. Di C ++ 03, bahasa tidak cukup kuat untuk menulis kelas sepertiauto_ptr
itu berperilaku dengan benar dan aman di semua skenario karena kompilator dan bahasa tidak dapat membedakan nilai l dan r sehingga beberapa "peretasan" digunakan untuk mendapatkan perilaku yang diinginkan sebagian besar waktu.Jawaban:
Standar C ++ mengatakan bahwa elemen STL harus "copy-constructible" dan "assignable." Dengan kata lain, suatu elemen harus dapat ditugaskan atau disalin dan kedua elemen tersebut secara logis independen.
std::auto_ptr
tidak memenuhi persyaratan ini.Ambil contoh kode ini:
Untuk mengatasi batasan ini, Anda harus menggunakan
std::unique_ptr
,std::shared_ptr
ataustd::weak_ptr
smart pointer atau boost setara jika Anda tidak memiliki C ++ 11. Berikut adalah dokumentasi pendorong perpustakaan untuk petunjuk pintar ini.sumber
unique_ptr
juga melarang penyalinan, sehingga operasi STL tertentu tidak akan berfungsi dengan benar kecuali mereka dapat menggunakan semantik gerakannya.std::unique_ptr
": bahwa templat kelas hanya bisa ada karena memindahkan semantik (spesifikasinya memerlukan referensi nilai ulang), sehingga pada dasarnya memerlukan C ++ 11. Namun (dan terkait) Standar C ++ 11 tidak lagi mengatakan bahwa tipe elemen STL harus "copy-constructible" dan "assignable"; cukup bergerak-konstruktif dan bergerak-ditugaskan. Memangunique_ptr
contoh hanya bergerak-membangun dan memindahkan-ditugaskan. Tapi begitu jugaauto_ptr
contoh! Sebagai konsekuensinya, dalam C ++ 11 Anda dapat melakukanauto_ptr
apa yang dapat Anda lakukanunique_ptr
.reset
danrelease
jika diperlukanreset
danrelease
", saya tidak melihat bagaimana itu berlaku untuk apa pun dalam komentar saya. Perhatikan bahwa keduanyaauto_ptr
danunique_ptr
kedua metode ini, dan mereka melakukan hal yang sama dalam kedua kasus.The semantik copy dari
auto_ptr
tidak kompatibel dengan kontainer.Secara khusus, menyalin satu
auto_ptr
ke yang lain tidak membuat dua objek yang sama karena satu telah kehilangan kepemilikan pointer.Lebih khusus lagi, menyalin
auto_ptr
penyebab salah satu salinan untuk melepaskan pointer. Yang mana dari sisa-sisa ini dalam wadah tidak ditentukan. Oleh karena itu, Anda dapat kehilangan akses ke pointer secara acak jika Anda menyimpannyaauto_ptrs
di dalam wadah.sumber
Dua artikel super bagus tentang hal ini:
sumber
auto_ptr
, tautan ini akan sangat membantu, saya yakin.sort()
, lebih jelas daripada semua jawaban di sini.Wadah STL harus dapat menyalin item yang Anda simpan di dalamnya, dan dirancang untuk mengharapkan yang asli dan salinannya setara. objek penunjuk otomatis memiliki kontrak yang sama sekali berbeda, di mana penyalinan membuat transfer kepemilikan. Ini berarti bahwa kontainer auto_ptr akan memperlihatkan perilaku aneh, tergantung penggunaan.
Ada uraian terperinci tentang apa yang salah dalam Efektif STL (Scott Meyers) item 8 dan juga deskripsi yang tidak terlalu terperinci dalam Efektif C ++ (Scott Meyers) item 13.
sumber
Wadah STL menyimpan salinan barang-barang yang terkandung. Ketika auto_ptr disalin, itu menetapkan ptr lama ke nol. Banyak metode wadah rusak oleh perilaku ini.
sumber
unique_ptr
seperti objek C ++ 11 yang tepat hanya dapat mentransfer kepemilikan sumber dayanya ketika dipindah-bangun atau-ditugaskan, memastikan bahwa pemrogram harus dengan sengaja melewati suatustd::move(sourceObject)
atau sementara, alih-alih memberikan nilai dan secara tidak sengaja / tidak terduga dimutasi oleh copy-tugas ... yang, seperti ditekankan secara menyeluruh di sini, adalah masalah intiauto_ptr
.C ++ 03 Standar (ISO-IEC 14882-2003) mengatakan dalam klausa 20.4.5 paragraf 3:
Standar C ++ 11 (ISO-IEC 14882-2011) mengatakan dalam lampiran D.10.1 paragraf 3:
Standar C ++ 14 (ISO-IEC 14882-2014) mengatakan dalam lampiran C.4.2 Lampiran D: fitur kompatibilitas:
sumber