Dulu umumnya direkomendasikan praktek terbaik 1 untuk penggunaan lewat ref const untuk semua jenis , kecuali untuk builtin jenis ( char
, int
, double
, dll), untuk iterator dan untuk benda fungsi (lambdas, kelas berasal dari std::*_function
).
Ini terutama benar sebelum keberadaan semantik bergerak . Alasannya sederhana: jika Anda melewati nilai, salinan objek harus dibuat dan, kecuali untuk objek yang sangat kecil, ini selalu lebih mahal daripada melewati referensi.
Dengan C ++ 11, kami telah mendapatkan semantik bergerak . Singkatnya, memindahkan semantik memungkinkan bahwa, dalam beberapa kasus, suatu objek dapat dilewati "dengan nilai" tanpa menyalinnya. Secara khusus, hal ini terjadi ketika objek yang Anda melewati sebuah nilai p .
Dalam dirinya sendiri, memindahkan objek masih setidaknya semahal melewati referensi. Namun, dalam banyak kasus suatu fungsi akan secara internal menyalin objek - yaitu akan mengambil kepemilikan dari argumen. 2
Dalam situasi ini kami memiliki pertukaran (disederhanakan) sebagai berikut:
- Kita dapat melewati objek dengan referensi, lalu menyalin secara internal.
- Kita bisa melewati objek dengan nilai.
"Pass by value" masih menyebabkan objek disalin, kecuali jika objek tersebut adalah nilai. Dalam hal nilai, objek dapat dipindahkan sebagai gantinya, sehingga kasus kedua tiba-tiba tidak lagi "menyalin, lalu memindahkan" tetapi "bergerak, lalu (berpotensi) bergerak lagi".
Untuk objek besar yang menerapkan konstruktor pemindahan yang tepat (seperti vektor, string ...), case kedua jauh lebih efisien daripada yang pertama. Oleh karena itu, disarankan untuk menggunakan pass by value jika fungsi tersebut mengambil kepemilikan dari argumen, dan jika jenis objek mendukung perpindahan efisien .
Catatan sejarah:
Bahkan, setiap kompiler modern harus dapat mencari tahu ketika melewati nilai mahal, dan secara implisit mengkonversi panggilan untuk menggunakan referensi ref jika memungkinkan.
Dalam teori. Dalam praktiknya, kompiler tidak selalu dapat mengubah ini tanpa merusak antarmuka biner fungsi. Dalam beberapa kasus khusus (ketika fungsi ini digarisbawahi) salinan akan benar-benar hilang jika kompiler dapat mengetahui bahwa objek asli tidak akan diubah melalui tindakan dalam fungsi.
Tetapi secara umum kompiler tidak dapat menentukan ini, dan munculnya semantik bergerak di C ++ telah membuat optimasi ini jauh kurang relevan.
1 Misalnya dalam Scott Meyers, Efektif C ++ .
2 Ini sering benar untuk konstruktor objek, yang dapat mengambil argumen dan menyimpannya secara internal untuk menjadi bagian dari keadaan objek yang dikonstruksi.