Ich verstehe nicht, warum dies kompiliert wird

80

Ich vermisse sicherlich etwas, aber ich verstehe nicht, warum dies kompiliert wird (sowohl mit g ++ als auch mit clang ++):

struct A
{
};
struct B
{
};

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

Zuallererst Bist ein Typ ... kein Wert. Wie soll ich diesen Code interpretieren?

Picaud Vincent
quelle
37
Dies ist bekannt als die ärgerlichste Analyse
alter igel
8
@alterigel Ist es wirklich? In diesem Fall gibt es keine Mehrdeutigkeit. Es kann nur eine Funktionsdeklaration sein. Dies kann keine A a(B());Variablendefinition oder Funktionsdeklaration sein.
Walnuss
8
Es würde Sie überraschen zu wissen, dass struct A{}; int main() { A(foo); } das so kompiliert wird , wie es ist , auch wenn Sie foonichts benennen.
Ayxan
20
@alterigel - das ist nicht die ärgerlichste Analyse. Schauen Sie sich die Beispiele auf der Seite an, auf die Sie verlinkt haben. Dies ist einfach eine Funktionsdeklaration.
Pete Becker
3
@PeteBecker, es könnte besser sein zu erklären, warum dies kein MVP ist, als nur zu behaupten, dass dies nicht der Fall ist, was Walnuss meiner Meinung nach bereits oben getan hat.
JPhi1618

Antworten:

84

Es wird als Deklaration einer Funktion mit dem Namen interpretiert a, die ein Argument vom Typ Bakzeptiert und zurückgibt A.

Brian
quelle
5
Und deshalb ist es Most und ärgerlich. Eine Lösung: (nicht, dass es tatsächlich etwas löst, da es die schlechte Konstruktion A a{B};
aufdeckt
23
@ user4581301 - es ist nicht die ärgerlichste Analyse. Es ist einfach eine Funktionsdeklaration.
Pete Becker
23
Es stellt sich also heraus, dass es nur eine meist ärgerliche
Analyse ist
11
Das seltsamste daran ist , dass C ++ nicht verschachtelte Funktionen zulässt, aber nicht erlauben Erklärungen innerhalb einer Funktion.
The_Sympathizer
6
Klingt nach einer guten Motivation, um C ++ Unterstützung für verschachtelte Funktionen hinzuzufügen. Sie wären nicht nur nützlich, sie würden diese seltsame Warze in ein vernünftiges Design verwandeln :)
Jeremy Friesner
15

Es ist einfach eine Funktionsdeklaration, die erklärt a, dass es sich um eine Funktion handelt, Adie einen unbenannten Parameter vom Typ zurückgibt und verwendetB .

Dies ist gültig, da Funktionsdeklarationen im Gegensatz zu Funktionsdefinitionen in Funktionsdefinitionen zulässig sind.

machine_1
quelle
13

Dieses Problem wird als die ärgerlichste Analyse bezeichnet . Die Zeile A a(B);kann als Deklaration einer Funktion mit dem Namen interpretiert werden, die aein Objekt vom Typ Azurückgibt und einen unbenannten Parameter vom Typ verwendet B.

Eine Möglichkeit, dieses Problem zu vermeiden, besteht darin, die in C ++ 11 eingeführte einheitliche Initialisierungssyntax zu verwenden, bei der Klammern anstelle von Klammern verwendet werden: A a{B};Gibt einen Fehler zurück. Die Zeile wird jetzt als Variablendeklaration interpretiert, die mit initialisiert wurdeB , die ein Typ anstelle eines Werts ist.

Hier finden Sie weitere Informationen:

Die ärgerlichste Analyse: Wie man sie erkennt und schnell behebt

G. Morin
quelle
12
Ich denke nicht, dass dies als " ärgerlichste Analyse " bezeichnet werden sollte. Es ist nur eine übliche Funktionsdeklaration, wie sie auch in C existiert. Es ist keine Mehrdeutigkeitsauflösung erforderlich, da die Zeile nur eine Funktionsdeklaration sein kann, sonst nichts. Schau dir deinen Link an. Die Beispiele unterscheiden sich alle davon.
Walnuss
3
Das stimmt zwar, aber es hängt mit der ärgerlichsten Analyse zusammen. Es ist nur so, dass dies auch einen Tippfehler beinhaltete, bei dem ein Typname allein anstelle einer Variablen oder eines Konstruktoraufrufs verwendet wurde, wie es wahrscheinlich die ursprüngliche Absicht war.
Miral
1
Ja, "Most Vexing Parse" ist in diesem Fall eine nützliche Antwort, obwohl der eigentliche Fall in der Frage nur "Slightly Vexing Parse" ist.
jpa
1
@wlanut: Die leeren Strukturen struct A { };sind in Standard C nicht gültig, selbst wenn einige Compiler dies zulassen. Lassen Sie die Zahnspange fallen und es würde dort kein Problem geben. In C wird durch Deklarieren oder Definieren struct Akein Typname erstellt A(Sie müssen ihm ein Präfix voranstellen structoder typedef struct A A;irgendwo hinzufügen, bevor Aes ohne das structPräfix verwendet wird). Auch in C gibt es keine alternative Analyse zur Funktionsdeklaration - using type name(...);kann einfach nie eine Variablendefinition sein; Es ist immer eine Funktionsdeklaration (oder ungültig). Der Code in der Frage ist nicht gültig in C.
Jonathan Leffler