2016-08-15 2 views
3

ich einen Code hier bei Cpp Quiz [Frage # 38] sahdrängendsten Parsen

#include <iostream> 

struct Foo 
{ 
    Foo(int d) : x(d) {} 
    int x; 
}; 

int main() 
{ 
    double x = 3.14; 

    Foo f(int(x)); 

    std::cout << f.x << std::endl; 

    return 0; 
} 

Es wird gesagt, dort, dass dieser Code schlecht ausgebildet ist, weil Foo f(int(x)); als Funktion Erklärung behandelt werden und nicht als Objekt Erklärung Geben Sie Foo ein. Soweit ich weiß, ist dies ein Beispiel für die meisten Ärger. Meine Frage ist, was ist diese Syntax int (x) in Aussage Foo f(int(x)); bedeutet? Bisher sah ich nur Funktionsdeklarationen wie:

  1. Foo f(int); und

  2. Foo f(int x);

Ist es gleich wie Foo f(int x);?

Antwort

2

Was ist diese Syntax int(x) in Anweisung Foo f(int(x)); bedeutet?

Die Klammern um x sind überflüssig und werden ignoriert. So int(x) ist das gleiche wie int x hier, bedeutet ein Parameter mit dem Namen x mit Typ int.

Ist es dasselbe wie Foo f(int x);?

Ja. Foo f(int(x));, ist eine Funktionsdeklaration, die f heißt, gibt Foo zurück, nimmt einen Parameter mit Name x mit Typ int.

Hier ist die Erklärung aus dem Standard. $8.2/1 Ambiguity resolution [dcl.ambig.res]:

(emphasis Mine)

Die Mehrdeutigkeit aus der Ähnlichkeit zwischen einem Funktions Stil Guss- und einer Erklärung in [stmt.ambig] auch in dem erwähnten entstehenden Rahmen einer Deklaration auftreten kann. In diesem Kontext ist die Wahl zwischen einer Funktionsdeklaration mit einem redundanten Satz von Klammern um einen Parameternamen und einer Objektdeklaration mit einer Funktionsartumsetzung wie dem Initialisierer. Genau wie bei den in [stmt.ambig], erwähnten Unklarheiten, ist die Lösung, jedes Konstrukt zu berücksichtigen, das möglicherweise eine Deklaration einer Deklaration sein könnte. [Hinweis: Eine Deklaration kann explizit disambiguiert werden, indem Klammern um das Argument hinzugefügt werden. Die Mehrdeutigkeit kann durch die Verwendung der Kopieinitialisierungs- oder Listeninitialisierungssyntax oder durch Verwendung einer Nichtfunktionsart vermieden werden.- Endnote] [Beispiel:

struct S { 
    S(int); 
}; 

void foo(double a) { 
    S w(int(a));  // function declaration 
    S x(int());  // function declaration 
    S y((int(a))); // object declaration 
    S y((int)a);  // object declaration 
    S z = int(a);  // object declaration 
} 

- Ende Beispiel]

So int(x) wird als Erklärung (des Parameters) in Betracht gezogen werden, anstatt eine Funktion Casts.

4

Das Problem ist, dass es aus mir unbekannten Gründen zulässig ist, Parameternamen in Prototypen in Klammern zu schreiben. So

Foo f(int(x)); 

als

Foo f(int x); 

interpretiert werden, die betrachtet wird als

Foo f(int); 

Das eigentliche Problem ist jedoch, dass C++ Autoren, auch aus mir unbekannten Gründen, beschlossen, dass es cool, um zwei verschiedene Syntaxformen für die fast identische Semantik (Instanzinitialisierung) zu haben.

Dies führt eine Syntax-Ambiguität ein, die "aufgelöst" wird, indem es sagt, "wenn etwas sowohl eine Deklaration als auch eine Definition sein kann, dann ist es eine Deklaration", die den Trap auslöst.

Aus diesem Grund muss ein C++ - Parser daher in der Lage sein, eine beliebig große Anzahl von Tokens zu analysieren, bevor er entscheiden kann, was die semantische Bedeutung des allerersten ist.

Dies wäre anscheinend nicht zu viel ein Problem außer Compiler-Autoren gewesen, aber aber bedeutet es, dass auch wer C++ Code liest, um es zu verstehen, in der Lage sein muss, dasselbe zu tun, und für uns Menschen ist das schwieriger. Von daher das "Ärgerlichste".

+1

Es ist erlaubt, weil es manchmal benötigt wird - wie 'int * a [10]' anders als 'int (* a) [10]' machen. Und niemand hat sich die Mühe gemacht, die Syntax bei Bedarf auf * nur * zu beschränken. –

+0

@BoPersson: Ich sah den Code bei [Ein verwirrendes Detail über die Most Vexing Parse] (http://stackoverflow.com/questions/7007817/a-confusing-detail-about-the-most-vexing-parse), und ehrlich gesagt verstehe ich es nicht :(. – NeonGlow

+0

@NeonGlow Die ruls ist das gleiche, erwarten, dass die Funktion zwei Parameter und die zweite ist ein Funktionszeiger. – songyuanyao