Ketepatan kode yang Anda tulis tidak boleh bergantung pada pengoptimalan. Seharusnya menampilkan hasil yang benar ketika dieksekusi pada "mesin virtual" C ++ yang mereka gunakan dalam spesifikasi.
Namun, apa yang Anda bicarakan lebih merupakan pertanyaan efisiensi. Kode Anda berjalan lebih baik jika dioptimalkan dengan kompiler yang mengoptimalkan RVO. Tidak apa-apa, untuk semua alasan yang ditunjukkan dalam jawaban lain.
Namun, jika Anda memerlukan pengoptimalan ini (seperti jika konstruktor salinan akan benar-benar menyebabkan kode Anda gagal), sekarang Anda berada di kehendak kompilator.
Saya pikir contoh terbaik dari ini dalam praktik saya sendiri adalah optimasi panggilan ekor:
int sillyAdd(int a, int b)
{
if (b == 0)
return a;
return sillyAdd(a + 1, b - 1);
}
Ini adalah contoh konyol, tetapi menunjukkan panggilan ekor, di mana suatu fungsi disebut tepat secara rekursif di akhir fungsi. Mesin virtual C ++ akan menunjukkan bahwa kode ini beroperasi dengan benar, meskipun saya dapat menyebabkan sedikit kebingungan mengapa saya repot menulis rutin tambahan seperti itu di tempat pertama. Namun, dalam implementasi praktis C ++, kami memiliki setumpuk, dan memiliki ruang terbatas. Jika dilakukan secara pedantik, fungsi ini harus mendorong setidaknya b + 1
tumpukan bingkai ke tumpukan seperti halnya penambahannya. Jika saya ingin menghitung sillyAdd(5, 7)
, ini bukan masalah besar. Jika saya ingin menghitung sillyAdd(0, 1000000000)
, saya bisa berada dalam kesulitan besar menyebabkan StackOverflow (dan bukan jenis yang baik ).
Namun, kita dapat melihat bahwa begitu kita mencapai garis balik terakhir, kita benar-benar selesai dengan semua yang ada di bingkai tumpukan saat ini. Kami benar-benar tidak perlu menyimpannya. Optimasi panggilan ekor memungkinkan Anda "menggunakan kembali" bingkai tumpukan yang ada untuk fungsi selanjutnya. Dengan cara ini, kita hanya perlu 1 frame stack, daripada b+1
. (Kita masih harus melakukan semua penambahan dan pengurangan yang konyol itu, tetapi mereka tidak mengambil lebih banyak ruang.) Akibatnya, optimasi mengubah kode menjadi:
int sillyAdd(int a, int b)
{
begin:
if (b == 0)
return a;
// return sillyAdd(a + 1, b - 1);
a = a + 1;
b = b - 1;
goto begin;
}
Dalam beberapa bahasa, optimisasi panggilan ekor secara eksplisit diperlukan oleh spesifikasi. C ++ bukan salah satunya. Saya tidak bisa mengandalkan kompiler C ++ untuk mengenali peluang optimisasi panggilan ekor ini, kecuali saya menggunakan kasus per kasus. Dengan versi Visual Studio saya, versi rilis melakukan optimasi panggilan ekor, tetapi versi debug tidak (menurut desain).
Dengan demikian akan buruk bagi saya untuk bergantung pada kemampuan untuk menghitung sillyAdd(0, 1000000000)
.