“İnt main () {(([] () {}) ());}” geçerli C ++ nasıl?


271

Son zamanlarda aşağıdaki ezoterik kod parçasına rastladım.

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

Daha okunabilir hale getirmek için aşağıdaki gibi yeniden biçimlendirin:

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

Ama (([](){})())geçerli kodun nasıl olduğunu bulamıyorum.

  • İşlev işaretçisi sözdizimi gibi görünmüyor.
  • Bazı operatör aşırı yükleme hilesi olamaz. Kod olduğu gibi derlenir.

Google, bu sembollü aramaya pek yardımcı olmadı. Ancak Visual Studio 2010'da derlenir ve hiçbir şey çıktılanmaz. Hata ve uyarı yoktu. Yani geçerli bir kod gibi görünüyor.

Javascript ve C fonksiyon işaretçileri dışında bu kadar tuhaf geçerli bir kod görmedim .

Birisi bunun nasıl geçerli C ++ olduğunu açıklayabilir misiniz?



31
bu bir c ++ 11 lambda kapatma

7
@Mysticial - İşe yaramaz olduğu için bu kod sizi gizliyor. Bu lambda bir şey yaparsa, işlev işaretleyicilerine benzer bir sözdizimine sahip olduğunu fark edersiniz (yakından ilişkilidir).
SChepurin

14
@Mysticial - "6 yıl C ++" - lambdalar C ++ 11'e yeni eklendi, bu yüzden hiç kimse onlarla bir yıl önce deneyime sahip değildi.
Pete Becker

50
Buradaki URL oldukça eğlenceli: "nasıl-int-main-geçerli-c"
tckmn

Yanıtlar:


283

Kod aslında boş bir lambda çağırır.

En baştan başlayalım: [](){}boş bir lambda ifadesidir .

Ardından, C ve C ++, sen Pars ifadeler sarmak ve onlar tam olarak aynı davranırlar onlarsız yazılmış gibi, bu yüzden lambda etrafında Pars ilk çifti yaptığı şey bu. Biz şimdi ([](){}).

Daha ()sonra, ilk ambalajlamadan sonra parens (boş) lambda'yı çağırır. Şu an buradayız([](){})()

Bütün ifade tekrar parens içine sarılır ve elde ederiz (([](){})()).

Sonunda ;ifadeyi bitirir. Biz varıyoruz (([](){})());.


† En azından C ++ 'da, ve arasında bir fark olduğu gibi bazı köşe vakaları T a_var; vardırdecltype(a_var)decltype((a_var)) .


7
Bir hançeri kaçırdım.
R. Martinho Fernandes

33
@ R.MartinhoFernandes: Hala birisine sıkışmıştı, bu yüzden gidip geri almak zorunda kaldım.
Xeo

1
Bir ifadenin etrafına () eklenmesinin anlambilimi değiştirdiği durumdan bahsettiğim için doğru oy vereceğim . Ama sonra hatırladım ki, bu gerçekten soruyla hiçbir ilgisi yok. Güzel cevap
sehe

2
Parantezler ayrıca en sinir bozucu ayrıştırma ayrıştırması durumunda bir programın anlamını değiştirmektedir: B foo(A())foo bir işlevdir (yalnızca parametre olarak işlev göstermek için bir işaretçiyi almak ve bir B döndürmek), B foo((A()))foo'da ise bir yapıcı çağrısını çağıran bir B nesnesidir. a Bir nesne (bu örnek bu durumda anonim bir geçicidir).
İlan N

1
@AdN: Bu artık bir ifade değil, bir deklarasyon.
Xeo
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.