Jika kita memiliki tiga fungsi (foo, bar, dan baz) yang dikomposisikan seperti ...
foo(bar(), baz())
Apakah ada jaminan oleh standar C ++ bahwa bar akan dievaluasi sebelum baz?
Jika kita memiliki tiga fungsi (foo, bar, dan baz) yang dikomposisikan seperti ...
foo(bar(), baz())
Apakah ada jaminan oleh standar C ++ bahwa bar akan dievaluasi sebelum baz?
Jawaban:
Tidak, tidak ada jaminan seperti itu. Ini tidak ditentukan menurut standar C ++.
Bjarne Stroustrup juga mengatakannya secara eksplisit dalam "The C ++ Programming Language" edisi ke-3 bagian 6.2.2, dengan beberapa alasan:
Kode yang lebih baik dapat dihasilkan tanpa adanya batasan pada urutan evaluasi ekspresi
Meskipun secara teknis ini mengacu pada bagian awal dari bagian yang sama yang mengatakan bahwa urutan evaluasi bagian ekspresi juga tidak ditentukan, yaitu
int x = f(2) + g(3); // unspecified whether f() or g() is called first
Dari [5.2.2] Panggilan fungsi,
Urutan evaluasi argumen tidak ditentukan. Semua efek samping dari evaluasi ekspresi argumen berlaku sebelum fungsi dimasukkan.
Oleh karena itu, tidak ada jaminan yang bar()
akan berjalan sebelumnya baz()
, hanya itu bar()
dan baz()
akan dipanggil sebelumnya foo
.
Perhatikan juga dari [5] Ekspresi bahwa:
kecuali jika dicatat [misalnya aturan khusus untuk
&&
dan||
], urutan evaluasi operan dari masing-masing operator dan subekspresi ekspresi individu, dan urutan efek samping yang terjadi, tidak ditentukan.
jadi meskipun Anda bertanya apakah bar()
akan dijalankan sebelumnya baz()
dalam foo(bar() + baz())
, urutannya masih belum ditentukan.
&
, &&
menjamin evaluasi kiri-ke-kanan: operan kedua tidak dievaluasi jika operan pertama adalah false
."
Tidak ada urutan tertentu untuk bar () dan baz () - satu-satunya hal yang dikatakan Standar adalah bahwa keduanya akan dievaluasi sebelum foo () dipanggil. Dari C ++ Standard, bagian 5.2.2 / 8:
Urutan evaluasi argumen tidak ditentukan.
bar
, lalu baris 1 baz
, lalu baris 2 bar
, dll.), Yang juga bagus. :-)
C ++ 17 menentukan urutan evaluasi untuk operator yang tidak ditentukan hingga C ++ 17. Lihat pertanyaan Apa jaminan urutan evaluasi yang diperkenalkan oleh C ++ 17? Tapi perhatikan ekspresi Anda
foo(bar(), baz())
memiliki urutan evaluasi yang masih belum ditentukan.
Di C ++ 11, teks yang relevan dapat ditemukan di 8.3.6 Argumen default / 9 (Emphasis mine)
Argumen default dievaluasi setiap kali fungsi dipanggil. Urutan evaluasi argumen fungsi tidak ditentukan . Akibatnya, parameter fungsi tidak boleh digunakan dalam argumen default, bahkan jika tidak dievaluasi.
Kata-kata yang sama digunakan oleh standar C ++ 14 juga, dan ditemukan di bawah bagian yang sama .
Seperti yang telah ditunjukkan oleh orang lain, standar ini tidak memberikan panduan apa pun tentang urutan evaluasi untuk skenario khusus ini. Urutan evaluasi ini kemudian diserahkan kepada kompilator, dan kompilator mungkin memiliki jaminan.
Penting untuk diingat bahwa standar C ++ sebenarnya adalah bahasa yang menginstruksikan kompiler untuk membuat kode assembly / mesin. Standar hanyalah salah satu bagian dari persamaan. Jika standarnya ambigu atau secara spesifik ditentukan oleh implementasi, Anda harus beralih ke compiler dan memahami cara menerjemahkan instruksi C ++ ke dalam bahasa mesin yang sebenarnya.
Jadi, jika urutan evaluasi adalah suatu persyaratan, atau setidaknya penting, dan menjadi kompatibel lintas-kompiler bukanlah suatu persyaratan, selidiki bagaimana kompiler Anda pada akhirnya akan menyatukannya, jawaban Anda mungkin terletak di sana. Perhatikan bahwa kompilator dapat mengubah metodologi itu di masa mendatang