Saya dengar auto_ptr
sudah tidak digunakan lagi di C ++ 11. Apa alasannya ini?
Saya juga ingin mengetahui perbedaan antara auto_ptr
dan shared_ptr
.
Jawaban:
Pengganti langsung untuk auto_ptr
(atau yang paling dekat dengan salah satunya) adalah unique_ptr
. Sejauh "masalah" berjalan, itu cukup sederhana: auto_ptr
mentransfer kepemilikan ketika sudah ditetapkan. unique_ptr
juga mentransfer kepemilikan, tetapi berkat kodifikasi semantik pemindahan dan keajaiban referensi nilai r, hal itu dapat dilakukan secara lebih alami. Ini juga "cocok" dengan pustaka standar lainnya secara jauh lebih baik (meskipun, dalam keadilan, beberapa di antaranya berkat sisa pustaka yang berubah untuk mengakomodasi semantik bergerak alih-alih selalu membutuhkan penyalinan).
Perubahan nama juga (IMO) merupakan hal yang disambut baik - auto_ptr
tidak benar-benar memberi tahu Anda banyak tentang apa yang coba diotomatiskan, sedangkan unique_ptr
deskripsi yang cukup masuk akal (jika singkat) tentang apa yang disediakan.
auto_ptr
nama: auto menyarankan otomatis seperti dalam variabel otomatis, dan ini mengacu pada satu hal yang auto_ptr
dilakukan: menghancurkan sumber daya yang dikelola di destruktornya (ketika keluar dari ruang lingkup).
auto_ptr
: open-std.org/jtc1/sc22/wg21/docs/papers/2005/…
std::sort
tidak memiliki spesialisasi untuk unique_ptr
. Sebaliknya itu ditentukan ulang untuk tidak pernah menyalin. Jadi auto_ptr
sebenarnya tidak bekerja dengan modern sort
. Namun C ++ 98/03 sort
adalah hanya sebuah contoh algoritma di sini: Setiap algoritma generik (std-disediakan atau pengguna tertulis) yang mengasumsikan bahwa sintaks copy memiliki copy semantik kemungkinan akan memiliki kesalahan run-time jika digunakan dengan auto_ptr
, karena auto_ptr
diam-diam bergerak dengan sintaks salin . Masalahnya jauh lebih besar dari sekadar sort
.
Saya menemukan jawaban yang ada bagus, tetapi dari PoV petunjuknya. IMO, jawaban yang ideal harus memiliki jawaban perspektif pengguna / programmer.
Hal pertama yang pertama (seperti yang ditunjukkan oleh Jerry Coffin dalam jawabannya)
shared_ptr: Jika Anda khawatir tentang membebaskan sumber daya / memori DAN jika Anda memiliki lebih dari satu fungsi yang dapat menggunakan objek SETIAP kali, maka gunakan shared_ptr.
Menurut DIFFERENT-Times, pikirkan situasi di mana object-ptr disimpan dalam beberapa struktur data dan kemudian diakses. Beberapa utas, tentu saja adalah contoh lain.
unique_ptr: Jika semua yang Anda khawatirkan adalah mengosongkan memori, dan akses ke objek adalah SEQUENTIAL, maka gunakan unique_ptr.
Dengan SEQUENTIAL, maksud saya, pada titik mana pun objek akan diakses dari satu konteks. Misalnya benda yang dibuat, dan digunakan segera setelah dibuat oleh pencipta. Setelah pembuatan, objek disimpan dalam struktur data PERTAMA . Kemudian salah satu objek dihancurkan setelah SATU struktur data atau dipindahkan ke struktur data KEDUA .
Dari baris ini, saya akan merujuk shared / unique _ptr sebagai smart-pointers. (auto_ptr juga merupakan smart-pointer TETAPI karena kekurangan dalam desainnya, yang membuatnya tidak digunakan lagi, dan yang menurut saya akan saya tunjukkan di baris berikutnya, mereka tidak boleh dikelompokkan dengan smart-pointer.)
Satu-satunya alasan terpenting mengapa auto_ptr tidak digunakan lagi untuk mendukung smart-pointer adalah assignment-semantics Jika bukan karena alasan itu, mereka akan menambahkan semua barang baru dari memindahkan semantik ke auto_ptr alih-alih menghentikannya. Karena tugas-semantik adalah fitur yang paling tidak disukai, mereka ingin fitur itu ditiadakan, tetapi karena ada kode tertulis yang menggunakan semantik itu, (yang tidak dapat diubah oleh komite standar), mereka harus melepaskan auto_ptr, bukan memodifikasinya.
Dari tautan: http://www.cplusplus.com/reference/memory/unique_ptr/operator=/
Jenis tugas yang didukung oleh unqiue_ptr
Dari: http://www.cplusplus.com/reference/memory/auto_ptr/operator=/
Jenis tugas yang didukung oleh auto_ptr
Sekarang datang ke alasan MENGAPA tugas menyalin itu sendiri sangat tidak disukai, saya memiliki teori ini:
Perilaku yang tidak diinginkan benar-benar tidak disukai dan karenanya tidak menyukai auto_ptr.
(Untuk 3.1415926536% programmer yang dengan sengaja ingin mentransfer kepemilikan C ++ 11 memberi mereka std :: move (), yang membuat niat mereka sangat jelas bagi semua magang yang akan membaca dan memelihara kode.)
auto_ptr
nilai menunjuk ke objek yang sama (karena mereka tidak memberikan kepemilikan bersama, yang pertama mati akan meninggalkan yang lain dengan warisan yang mematikan; ini juga berlaku untuk unique_ptr
penggunaan), dapatkah Anda menyarankan apa yang dimaksudkan di yang tersisa 96.8584073465% dari semua penggunaan?
*a=*b;
Di sini hanya nilai b yang disalin ke a. Semoga Kepemilikan a dan b tetap dimiliki oleh orang yang sama. Anda menyebutkan seperti kepemilikan akan ditransfer. Bagaimana jadinya?
auto_ptr
objek itu sendiri. Menugaskan ke / dari nilai menunjuk ke tidak akan berpengaruh pada, atau relevansi dengan, kepemilikan. Saya harap Anda tidak masih menggunakan auto_ptr
?
Namun yang lain menjelaskan perbedaannya ....
Secara fungsional, C ++ 11 std::unique_ptr
adalah "tetap" std::auto_ptr
: keduanya cocok ketika - pada titik waktu mana pun selama eksekusi - harus ada satu pemilik smart-pointer untuk objek yang diarahkan ke.
Perbedaan krusial adalah dalam konstruksi salinan atau penugasan dari penunjuk cerdas lain yang tidak kedaluwarsa, yang ditunjukkan pada =>
baris di bawah ini:
std::auto_ptr<T> ap(...);
std::auto_ptr<T> ap2(get_ap_to_T()); // take expiring ownership
=> std::auto_ptr<T> ap3(ap); // take un-expiring ownership ala ap3(ap.release());
ap->xyz; // oops... can still try to use ap, expecting it to be non-NULL
std::unique_ptr<T> up(...);
std::unique_ptr<T> up2(get_up_to_T()); // take expiring ownership
=> std::unique_ptr<T> up3(up); // COMPILE ERROR: can't take un-expiring ownership
=> std::unique_ptr<T> up4(std::move(up)); // EXPLICIT code allowed
=> std::unique_ptr<T> up4(up.release()); // EXPLICIT code allowed
Di atas, ap3
diam-diam "mencuri" kepemilikan *ap
, meninggalkan ap
set ke anullptr
, dan masalahnya adalah itu bisa terjadi terlalu mudah, tanpa programmer memikirkan keamanannya.
Misalnya, jika a class
/ struct
memiliki std::auto_ptr
anggota, maka membuat salinan sebuah instance akan release
membuat pointer dari instance tersebut akan disalin: itu semantik yang aneh dan sangat membingungkan karena biasanya menyalin sesuatu tidak akan mengubahnya. Sangat mudah bagi penulis class / struct untuk mengabaikan rilis pointer ketika bernalar tentang invariants dan state, dan akibatnya secara tidak sengaja mencoba untuk dereferensi smart-pointer sementara null, atau hanya tidak memiliki akses / kepemilikan yang diharapkan dari data yang diarahkan ke.
auto_ptr tidak dapat digunakan dalam penampung STL karena memiliki konstruktor salinan yang tidak memenuhi persyaratan penampung CopyConstructible . unique_ptr tidak mengimplementasikan konstruktor salinan, jadi container menggunakan metode alternatif. unique_ptr dapat digunakan dalam container dan lebih cepat untuk algoritme std daripada shared_ptr.
#include <iostream>
#include <type_traits>
#include <vector>
#include <memory>
using namespace std;
int main() {
cout << boolalpha;
cout << "is_copy_constructible:" << endl;
cout << "auto_ptr: " << is_copy_constructible< auto_ptr<int> >::value << endl;
cout << "unique_ptr: " << is_copy_constructible< unique_ptr<int> >::value << endl;
cout << "shared_ptr: " << is_copy_constructible< shared_ptr<int> >::value << endl;
vector<int> i_v;
i_v.push_back(1);
cout << "i_v=" << i_v[0] << endl;
vector<int> i_v2=i_v;
cout << "i_v2=" << i_v2[0] << endl;
vector< unique_ptr<int> > u_v;
u_v.push_back(unique_ptr<int>(new int(2)));
cout << "u_v=" << *u_v[0] << endl;
//vector< unique_ptr<int> > u_v2=u_v; //will not compile, need is_copy_constructible == true
vector< unique_ptr<int> > u_v2 =std::move(u_v); // but can be moved
cout << "u_v2=" << *u_v2[0] << " length u_v: " <<u_v.size() << endl;
vector< shared_ptr<int> > s_v;
shared_ptr<int> s(new int(3));
s_v.push_back(s);
cout << "s_v=" << *s_v[0] << endl;
vector< shared_ptr<int> > s_v2=s_v;
cout << "s_v2=" << *s_v2[0] << endl;
vector< auto_ptr<int> > a_v; //USAGE ERROR
return 0;
}
>cxx test1.cpp -o test1
test1.cpp: In function âint main()â:
test1.cpp:33:11: warning: âauto_ptrâ is deprecated (declared at /apps/hermes/sw/gcc/gcc-4.8.5/include/c++/4.8.5/backward/auto_ptr.h:87) [-Wdeprecated-declarations]
vector< auto_ptr<int> > a_v; //USAGE ERROR
^
>./test1
is_copy_constructible:
auto_ptr: false
unique_ptr: false
shared_ptr: true
i_v=1
i_v2=1
u_v=2
s_v=3
s_v2=3