Bagaimana "int main () {(([] () {}) ());}" C ++ valid?


271

Baru-baru ini saya menemukan potongan kode esoterik berikut.

int main(){(([](){})());}

Format ulang sebagai berikut untuk membuatnya lebih mudah dibaca:

int main(){
    (([](){})());   //  Um... what?!?!
}

Tapi saya tidak bisa mengerti bagaimana (([](){})())kode yang valid.

  • Itu tidak terlihat seperti sintaks fungsi pointer.
  • Tidak mungkin ada trik kelebihan operator. Kode mengkompilasi apa adanya.

Google tidak banyak membantu dengan pencarian semua simbol ini. Tapi itu dikompilasi dalam Visual Studio 2010 dan tidak menghasilkan apa-apa. Tidak ada kesalahan, dan tidak ada peringatan. Jadi sepertinya kode yang valid.

Aku belum pernah melihat kode yang valid yang begitu aneh di luar Javascript dan C fungsi pointer .

Bisakah seseorang menjelaskan bagaimana ini valid C ++?



31
itu adalah penutupan c ++ 11 lambda

7
@Mysticial - Kode ini membingungkan Anda karena tidak berguna. Jika lambda ini akan melakukan sesuatu, Anda akan mengenalinya memiliki sintaksis yang mirip dengan pointer fungsi (yang terkait erat).
— SChepurin

14
@Mysticial - "6 tahun C ++" - lambdas baru saja ditambahkan di C ++ 11, jadi tidak ada yang punya pengalaman dengan mereka sebelum satu tahun yang lalu.
— Pete Becker

50
URL di sini cukup menghibur: "how-is-int-main-valid-c"
— tckmn

Jawaban:


283

Kode dasarnya memanggil lambda kosong.

Mari kita mulai dari awal: [](){}adalah ekspresi lambda kosong .

Kemudian, dalam C dan C ++, Anda dapat membungkus ekspresi dalam parens dan mereka berperilaku persis sama † seolah-olah ditulis tanpa mereka, jadi itulah yang dilakukan sepasang parens pertama di sekitar lambda. Kami sekarang di([](){}) .

Kemudian, ()setelah orangtua pembungkus pertama memanggil lambda (kosong). Kami sekarang di([](){})()

Seluruh ekspresi dibungkus dalam parens lagi dan kita dapatkan (([](){})()) .

Akhirnya, ;akhiri pernyataan itu. Kami tiba di (([](){})());.


† Ada beberapa kasus sudut setidaknya dalam C ++, seperti T a_var; ada perbedaan antara decltype(a_var)dandecltype((a_var)) .


7
Melewatkan belati.
— R. Martinho Fernandes

33
@ R.MartinhoFernandes: Itu masih macet di seseorang, jadi saya harus pergi dan mengambilnya.
— Xeo

1
Saya akan memilih dengan tepat menyebutkan kasus di mana menambahkan () di sekitar ekspresi mengubah semantik. Tapi kemudian saya ingat bahwa tidak ada hubungannya dengan pertanyaan, sungguh. Jawaban yang bagus
— lihat

2
Tanda kurung juga mengubah arti program dalam kasus disambiguasi parse yang paling menjengkelkan: B foo(A())foo adalah fungsi (mengambil pointer berfungsi sebagai hanya parameter dan mengembalikan B) sedangkan di B foo((A()))foo adalah objek B dibangun memohon pengambilan konstruktor a A object (instance mana yang bersifat anonim sementara dalam kasus ini).
— Iklan N

1
@ ADN: Itu bukan ekspresi lagi, tapi deklarasi.
— Xeo
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.