Saya tidak mengerti mengapa ini mengkompilasi

80

Saya pasti melewatkan sesuatu, tapi saya tidak mengerti mengapa ini mengkompilasi (dengan g ++ & clang ++):

struct A
{
};
struct B
{
};

int main()
{
  A a(B);
}

Pertama-tama, Badalah tipe ... bukan nilai. Bagaimana saya menafsirkan kode ini?

Picaud Vincent
sumber
37
Ini dikenal sebagai Parse Terbanyak
ubah igel
8
@alterigel Benarkah? Dalam hal ini tidak ada ambiguitas. Ini hanya bisa menjadi deklarasi fungsi. Bukan A a(B());yang bisa menjadi definisi variabel atau deklarasi fungsi.
kenari
8
Anda akan terkejut mengetahui bahwa struct A{}; int main() { A(foo); } mengkompilasi apa adanya , bahkan jika footidak menyebutkan nama apa pun.
Ayxan
20
@alterigel - ini bukan parse yang paling menjengkelkan. Lihatlah contoh-contoh di halaman yang Anda tautkan. Ini hanyalah deklarasi fungsi.
Pete Becker
3
@PeteBecker, mungkin lebih baik untuk menjelaskan mengapa ini bukan MVP daripada hanya menyatakan bahwa itu bukan, yang saya percaya walnut sudah melakukannya di atas.
JPhi1618

Jawaban:

84

Ini ditafsirkan sebagai deklarasi fungsi bernama a, yang mengambil satu argumen tipe Bdan kembali A.

Brian
sumber
5
Dan itulah sebabnya mengapa Most dan Vexing. Solusi: (bukannya itu benar-benar memecahkan apa pun karena memperlihatkan konstruksi yang buruk)A a{B};
user4581301
23
@ user4581301 - ini bukan parsing yang paling menjengkelkan. Ini hanya deklarasi fungsi.
Pete Becker
23
Jadi ternyata itu hanya sebagian besar menjengkelkan ...
MooseBoys
11
Bagian paling aneh tentang hal itu adalah bahwa C ++ tidak memungkinkan fungsi bersarang, tetapi tidak memungkinkan deklarasi dalam fungsi.
The_Sympathizer
6
Kedengarannya seperti motivasi yang baik untuk menambahkan dukungan untuk fungsi bersarang ke C ++; tidak hanya berguna, mereka akan mengubah kutil aneh ini menjadi desain yang masuk akal :)
Jeremy Friesner
15

Ini hanyalah deklarasi fungsi yang menyatakan asebagai fungsi yang mengembalikan Adan mengambil satu parameter tipe tanpa nama B.

Ini valid karena deklarasi fungsi yang bertentangan dengan definisi fungsi diizinkan dalam definisi fungsi.

machine_1
sumber
13

Masalah ini dikenal sebagai parse yang paling menjengkelkan . Baris A a(B);dapat diartikan sebagai deklarasi fungsi yang bernama amengembalikan objek tipe Adan mengambil parameter tipe yang tidak disebutkan namanya B.

Salah satu cara untuk menghindari masalah ini adalah dengan menggunakan sintaks inisialisasi seragam yang diperkenalkan dalam C ++ 11, yang terdiri dari penggunaan kurung kurawal alih-alih tanda kurung: A a{B};mengembalikan kesalahan. Baris sekarang ditafsirkan sebagai deklarasi variabel diinisialisasi dengan B, yang merupakan tipe, bukan nilai.

Berikut informasi lebih lanjut:

The Most Vexing Parse: Cara Menemukan dan Memperbaikinya dengan Cepat

G. Morin
sumber
12
Saya tidak berpikir ini harus disebut " parse paling menjengkelkan ". Ini hanya deklarasi fungsi biasa karena juga ada di C. Tidak ada resolusi ambiguitas yang diperlukan karena garis hanya bisa menjadi deklarasi fungsi, tidak ada yang lain. Lihatlah tautan Anda. Semua contoh berbeda dari ini.
walnut,
3
Meskipun itu benar, ini terkait dengan parse yang paling menjengkelkan. Hanya saja ini juga termasuk salah ketik di mana nama ketik digunakan sendiri, bukan variabel atau panggilan konstruktor, seperti yang mungkin maksud aslinya.
Miral
1
Ya, "Most Vexing Parse" adalah jawaban yang berguna dalam kasus ini, meskipun kasus sebenarnya dalam pertanyaan itu hanyalah "Slightly Vexing Parse".
jpa
1
@ wlanut: Struktur kosong struct A { };tidak valid dalam standar C, bahkan jika beberapa kompiler mengizinkannya. Jatuhkan kawat gigi dan tidak akan ada masalah di sana. Juga, di C, menyatakan atau mendefinisikan struct Atidak membuat nama jenis A(Anda harus awalan dengan struct, atau menambahkan typedef struct A A;tempat sebelum Adigunakan tanpa structawalan). Juga di C, tidak ada alternatif parse ke deklarasi fungsi - menggunakan type name(...);tidak bisa menjadi definisi variabel; selalu merupakan deklarasi fungsi (atau tidak valid). Kode dalam pertanyaan tidak valid dalam C.
Jonathan Leffler