Dilihat oleh komentar
habr.com/en/post/460831/#comment_20416435 di pos berikutnya dan diskusi yang terbuka di sana, artikel tentang cara menyampaikan argumen dengan benar ke konstruktor atau setter tidak akan menghalangi HabrΓ©. StackOverflow memiliki banyak materi serupa, tetapi saya tidak ingat sesuatu di sini.
Karena contoh dalam artikel itu sepenuhnya benar, dan penulis artikel itu benar sekali. Berikut ini sebuah contoh:
Kode tersebut memungkinkan Anda untuk mencakup semua (well, hampir semua) opsi yang mungkin untuk menggunakan kelas:
std::string first{"abc"}, last{"def"}; person p1{first, last};
Bandingkan dengan metode lama, ketika dilewatkan oleh const &: sudah pasti lebih buruk, karena tidak termasuk opsi (3):
Alternatif dengan && juga lebih buruk, tetapi berlawanan arah:
Jika Anda tidak takut dengan ledakan kombinatorial, Anda dapat memberikan kesempatan untuk && (tapi mengapa? Tidak akan ada peningkatan kecepatan, pengoptimal tidak tertidur):
Atau hal yang sama, hanya dengan templat (tapi sekali lagi, mengapa?):
Bahkan jika Anda tidak memiliki std :: string, tetapi beberapa objek dari kelas besar Anda sendiri, dan Anda ingin orang membuatnya bergerak (dan tidak menyalin), maka dalam hal ini lebih baik untuk melarang konstruktor untuk menyalin dari kelas besar ini daripada meneruskannya ke mana-mana oleh &&. Ini lebih dapat diandalkan, dan kode lebih pendek.
Akhirnya, beberapa opsi tentang cara TIDAK LAYAK:
Dan jangan:
Mengapa ini terjadi, apa prinsip dasarnya? Ini sederhana: sebuah objek, sebagai aturan, harus SENDIRI sifatnya.
Jika objek tidak ingin memiliki sesuatu, maka itu dapat memiliki shared_ptr untuk "sesuatu" ini. Ngomong-ngomong, dalam hal ini shared_ptr juga harus diteruskan oleh nilai, dan bukan oleh tautan konstan - tidak ada perbedaan dengan contoh pertama di awal artikel:
Harap dicatat: std :: move untuk shared_ptr benar-benar legal, ini menghilangkan overhead dari penguncian penghitung tautan shared_ptr dalam memori (ratusan siklus CPU) dan kenaikannya. Itu tidak mempengaruhi masa objek dan tautan lain ke sana. Tetapi (X) dapat dilakukan, tentu saja, hanya jika tautan psh dalam kode di bawah ini tidak lagi diperlukan.
Moral: jangan gunakan const & secara umum. Terlihat sesuai dengan keadaan.
PS
Gunakan {} alih-alih () saat meneruskan parameter konstruktor. Fashionable, modern, awet muda.
PPS
Sebagai kesimpulan, satu hal lagi: std :: move () sebenarnya tidak memindahkan apa pun dan dengan sendirinya diterjemahkan menjadi instruksi assembler nol. Semua yang std :: move () lakukan adalah meletakkan "sticky label" khusus pada tautan, mengubahnya menjadi referensi nilai&& -. Dan lebih lanjut adalah mungkin dengan label ini untuk secara terpisah "mencocokkan" jenis parameter fungsi (misalnya, untuk memiliki kelebihan fungsi terpisah untuk parameter && - dan parameter terpisah untuk & -parameter). Arti dari label && - adalah untuk mengaktifkan kode panggilan untuk memberi tahu yang dipanggil: βjika Anda mau, Anda bisa makan nilainya dari tautan ini, saya tidak lagi membutuhkannya; tetapi hanya jika Anda makan, tinggalkan tulangnya, maka saya masih perlu memanggil destruktor untuk kerangka yang tersisa. " Dengan kesuksesan yang sama, akan mungkin untuk mengirimkan tautan & biasa (Anda juga dapat menggunakan objek untuk "memakannya"), tetapi dengan && semantik lebih baik, karena Anda tidak akan bingung: di mana Anda bisa makan, dan di mana Anda hanya bisa mencium.
Dalam hal ini, nama std :: move () harus dikenali sebagai sangat tidak berhasil. Akan benar untuk menyebutnya std :: eat_me_if_you_want () atau std :: bon_appetit (). Tetapi std :: move () lebih pendek.