Howard sudah menjawab pertanyaan itu dengan baik, dan Nicol membuat beberapa poin bagus tentang manfaat memiliki satu tipe penunjuk bersama standar, daripada banyak yang tidak kompatibel.
Sementara saya sepenuhnya setuju dengan keputusan komite, saya pikir ada beberapa manfaat untuk menggunakan unsynchronized shared_ptr
jenis -seperti dalam kasus khusus , jadi saya sudah menyelidiki topik beberapa kali.
Jika saya tidak menggunakan beberapa utas, atau jika saya menggunakan banyak utas tetapi tidak berbagi kepemilikan penunjuk di utas, penunjuk cerdas atom berlebihan.
Dengan GCC, saat program Anda tidak menggunakan beberapa utas, shared_ptr tidak menggunakan operasi atomik untuk refcount tersebut. Ini dilakukan dengan memperbarui jumlah referensi melalui fungsi pembungkus yang mendeteksi apakah program multithread (pada GNU / Linux ini dilakukan hanya dengan mendeteksi apakah program terhubung ke libpthread.so
) dan mengirimkannya ke operasi atom atau non-atomik sesuai.
Saya menyadari bertahun-tahun yang lalu bahwa karena GCC shared_ptr<T>
diimplementasikan dalam hal __shared_ptr<T, _LockPolicy>
kelas dasar , dimungkinkan untuk menggunakan kelas dasar dengan kebijakan penguncian utas tunggal bahkan dalam kode multithread, dengan menggunakan secara eksplisit __shared_ptr<T, __gnu_cxx::_S_single>
. Sayangnya, karena itu bukan kasus penggunaan yang dimaksudkan, ia tidak bekerja secara optimal sebelum GCC 4.9, dan beberapa operasi masih menggunakan fungsi pembungkus sehingga dikirim ke operasi atomik meskipun Anda secara eksplisit meminta _S_single
kebijakan tersebut. Lihat poin (2) di http://gcc.gnu.org/ml/libstdc++/2007-10/msg00180.htmluntuk mengetahui detail selengkapnya dan patch ke GCC untuk memungkinkan implementasi non-atomik digunakan bahkan dalam aplikasi multithread. Saya duduk di tambalan itu selama bertahun-tahun tetapi akhirnya saya berkomitmen untuk GCC 4.9, yang memungkinkan Anda menggunakan templat alias seperti ini untuk menentukan jenis penunjuk bersama yang tidak aman untuk utas, tetapi sedikit lebih cepat:
template<typename T>
using shared_ptr_unsynchronized = std::__shared_ptr<T, __gnu_cxx::_S_single>;
Jenis ini tidak akan dapat dioperasikan dengan std::shared_ptr<T>
dan hanya akan aman digunakan jika ada jaminan bahwa shared_ptr_unsynchronized
objek tidak akan pernah dibagikan di antara utas tanpa sinkronisasi tambahan yang disediakan pengguna.
Ini tentu saja sepenuhnya non-portabel, tetapi terkadang tidak apa-apa. Dengan peretasan preprocessor yang tepat, kode Anda masih akan berfungsi dengan baik dengan implementasi lain jika shared_ptr_unsynchronized<T>
merupakan alias shared_ptr<T>
, hanya akan sedikit lebih cepat dengan GCC.
Jika Anda menggunakan GCC sebelum versi 4.9, Anda dapat menggunakannya dengan menambahkan _Sp_counted_base<_S_single>
spesialisasi eksplisit ke kode Anda sendiri (dan memastikan tidak ada yang membuat instance __shared_ptr<T, _S_single>
tanpa menyertakan spesialisasi, untuk menghindari pelanggaran ODR.) Menambahkan spesialisasi std
jenis semacam itu secara teknis tidak ditentukan, tetapi akan berfungsi dalam praktik, karena dalam hal ini tidak ada perbedaan antara saya menambahkan spesialisasi ke GCC atau Anda menambahkannya ke kode Anda sendiri.