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?


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.


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.


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


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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.