std :: auto_ptr ke std :: unique_ptr

185

Dengan standar baru datang (dan bagian sudah tersedia di beberapa kompiler), tipe baru std::unique_ptrseharusnya menjadi pengganti std::auto_ptr.

Apakah penggunaannya benar-benar tumpang tindih (sehingga saya dapat melakukan global menemukan / mengganti kode saya (bukan bahwa saya akan melakukan ini, tetapi jika saya melakukannya)) atau haruskah saya menyadari beberapa perbedaan yang tidak jelas dari membaca dokumentasi?

Juga jika itu adalah pengganti langsung, mengapa memberinya nama baru daripada hanya meningkatkan std::auto_ptr?

Martin York
sumber

Jawaban:

219

Anda tidak dapat melakukan pencarian / penggantian global karena Anda dapat menyalin auto_ptr(dengan konsekuensi yang diketahui), tetapi unique_ptrhanya dapat dipindahkan. Seperti apa pun bentuknya

std::auto_ptr<int> p(new int);
std::auto_ptr<int> p2 = p; 

harus menjadi setidaknya seperti ini

std::unique_ptr<int> p(new int);
std::unique_ptr<int> p2 = std::move(p);

Adapun perbedaan lainnya, unique_ptrdapat menangani array dengan benar (itu akan memanggil delete[], sementara auto_ptrakan berusaha memanggil delete.

Cubbi
sumber
101
di sisi lain, melakukan ini menemukan / mengganti hanya akan menghasilkan kesalahan kompilasi, itu tidak akan merusak kode sejauh yang saya bisa lihat. Jadi aman untuk dilakukan, jika Anda memperbaiki kesalahan kompilasi secara manual sesudahnya
jalf
7
@jalf: Memang, saya tidak bisa memikirkan contoh tandingan yang akan didefinisikan dengan baik dengan auto_ptrs dan UB dengan unique_ptrs.
Cubbi
1
jadi sepertinya unique_ptr merupakan peningkatan dari auto_ptr: support array & hapus ambiguitas
Baiyan Huang
92

std::auto_ptrdan std::unique_ptrtidak kompatibel di suatu tempat dan penurunan penggantian pada orang lain. Jadi, tidak ada temukan / ganti tidak cukup baik. Namun, setelah menemukan / mengganti bekerja melalui kesalahan kompilasi harus memperbaiki semuanya kecuali kasus sudut aneh. Sebagian besar kesalahan kompilasi akan membutuhkan penambahan a std::move.

  • Variabel ruang lingkup fungsi:
    100% kompatibel, selama Anda tidak meneruskannya dengan nilai ke fungsi lain.
  • Jenis pengembalian:
    tidak 100% kompatibel tetapi 99% kompatibel tampaknya tidak salah.
  • Parameter fungsi berdasarkan nilai:
    100% kompatibel dengan satu peringatan, unique_ptrs harus dilewati melalui std::movepanggilan. Yang ini sederhana karena kompiler akan mengeluh jika Anda tidak melakukannya dengan benar.
  • Parameter fungsi dengan referensi:
    100% kompatibel.
  • Variabel anggota kelas:
    Yang ini rumit. std::auto_ptrSemantik salinan itu jahat. Jika kelas tidak mengizinkan penyalinan maka std::unique_ptrada setetes penggantian. Namun, jika Anda mencoba memberikan semantik salinan kelas yang wajar, Anda perlu mengubah std::auto_ptrkode penanganan. Ini sederhana karena kompiler akan mengeluh jika Anda tidak melakukannya dengan benar. Jika Anda mengizinkan penyalinan kelas dengan std::auto_ptranggota tanpa kode khusus, maka malulah Anda dan semoga sukses.

Singkatnya, std::unique_ptrtidak terputus std::auto_ptr. Itu tidak diizinkan pada waktu kompilasi perilaku yang sering kesalahan saat menggunakan a std::auto_ptr. Jadi jika Anda menggunakan std::auto_ptrdengan perawatan yang dibutuhkan, beralih ke std::unique_ptrharus sederhana. Jika Anda mengandalkan std::auto_ptrperilaku aneh, Anda tetap harus memperbaiki kode Anda.

deft_code
sumber
8
+1 untuk "Anda tetap harus memperbaiki kode Anda". auto_ptrs hanya baik untuk apa yang dikatakan baik untuk 20.4.5 / 3.
Cubbi
8
Biarkan saya menambahkan ini bahwa Anda harus, dengan segala cara, mengganti auto_ptr dengan unique_ptr dalam kode Anda dan memperbaiki kesalahan kompilasi. Anda akan terkejut betapa banyak bug ini akan terungkap.
Bartosz Milewski
36

AFAIK, unique_ptrbukan pengganti langsung. Kelemahan utama yang diperbaiki adalah pengalihan kepemilikan secara implisit.

std::auto_ptr<int> a(new int(10)), b;
b = a; //implicitly transfers ownership

std::unique_ptr<int> a(new int(10)), b;
b = std::move(a); //ownership must be transferred explicitly

Di sisi lain, unique_ptrakan memiliki kemampuan yang sama sekali baru: mereka dapat disimpan dalam wadah.

UncleBens
sumber
8
Scott Meyers juga menyebutkan dalam "Efektif C ++" (Edisi ke-3) Butir 13 (halaman 64) bahwa wadah STL mengharuskan isinya menunjukkan perilaku penyalinan "normal", sehingga wadah auto_ptrtidak diperbolehkan.
Qiang Xu
31

Herb Sutter memiliki penjelasan yang bagus tentang GotW # 89 :

Apa masalahnya dengan auto_ptr? auto_ptr paling dikarakterisasi sebagai upaya berani untuk membuat unique_ptr sebelum C ++ telah memindahkan semantik. auto_ptr sekarang sudah tidak digunakan lagi, dan tidak boleh digunakan dalam kode baru.

Jika Anda memiliki auto_ptr di basis kode yang ada, ketika Anda mendapat kesempatan mencoba melakukan pencarian-dan-ganti global dari auto_ptr ke unique_ptr; sebagian besar kegunaan akan bekerja sama, dan mungkin mengekspos (sebagai kesalahan waktu kompilasi) atau memperbaiki (diam-diam) satu atau dua bug yang Anda tidak tahu Anda miliki.

Dengan kata lain, sementara pencarian dan penggantian global dapat "memecah" kode Anda untuk sementara waktu, Anda harus tetap melakukannya: Mungkin perlu waktu untuk memperbaiki kesalahan kompilasi, tetapi akan menghemat lebih banyak masalah dalam jangka panjang.

ValarDohaeris
sumber
Tautan bagus. Terima kasih banyak!
fotNelton