Frage Warum erlaubt uns C ++, den Variablennamen in Klammern zu setzen, wenn eine Variable deklariert wird?


Zum Beispiel eine Erklärung wie folgt:

int (x) = 0;

Oder auch das:

int (((x))) = 0;

Ich stolperte darüber, weil ich in meinem Code ein ähnliches Fragment wie das folgende hatte:

struct B
{
};

struct C
{
  C (B *) {}
  void f () {};
};

int main()
{
  B *y;
  C (y);
}

Offensichtlich wollte ich ein Objekt konstruieren C was dann etwas Nützliches in seinem Destruktor tun würde. Wie auch immer, der Compiler behandelt C (y); als eine Erklärung der Variablen y mit Typ C und so druckt es einen Fehler über y Neudefinition. Interessant ist, dass wenn ich es schreibe C (y).f () oder als etwas ähnliches C (static_cast<B*> (y)) Es wird wie beabsichtigt kompiliert. Der beste moderne Workaround ist zu verwenden {} natürlich in Konstruktoraufruf.

Wie ich später herausgefunden habe, ist es möglich, Variablen wie zu deklarieren int (x) = 0; oder auch int (((x))) = 0; aber ich habe noch nie jemanden gesehen, der solche Deklarationen benutzt. Ich bin also interessiert - was ist der Zweck einer solchen Möglichkeit, weil ich jetzt sehe, dass es nur den Fall ähnlich dem berüchtigten "ärgerlichsten Parse" schafft und nichts nützliches hinzufügt?


76
2018-04-16 13:05


Ursprung


Antworten:


Gruppierung.

Beachten Sie als besonderes Beispiel, dass Sie eine Variable vom Funktionstyp wie z

int f(int);

Nun, wie würdest du einen Zeiger auf so etwas erklären?

int *f(int);

Nein, funktioniert nicht! Dies wird als eine Funktion interpretiert, die zurückkehrt int*. Sie müssen die Klammern hinzufügen, damit sie korrekt analysiert werden:

int (*f)(int);

Der gleiche Deal mit Arrays:

int *x[5];   // array of five int*
int (*x)[5]; // pointer to array of five int

76
2018-04-16 13:11



In solchen Deklarationen dürfen Klammern verwendet werden, da die Deklaration aus syntaktischer Sicht immer so aussieht:

<front type> <specification>;

Zum Beispiel in der folgenden Deklaration:

int* p[2];

Der "Fronttyp" ist int (nicht int*) und die "Spezifikation" ist * p[2].

Die Regel besteht darin, dass Sie im Abschnitt "Spezifikation" eine beliebige Anzahl von Klammern verwenden können, da sie manchmal unvermeidlich sind, um zu disambiguieren. Beispielsweise:

int* p[2]; // array of 2 pointers to int; same as int (*p[2]);
int (*p)[2]; // pointer to an array of 2 ints

Der Zeiger auf ein Array ist ein seltener Fall, jedoch die gleiche Situation, die Sie mit einem Zeiger auf Funktion haben:

int (*func(int)); // declares a function returning int*
int (*func)(int); // declares a pointer to function returning int

Dies ist die direkte Antwort auf Ihre Frage. Wenn deine Frage über die Aussage ist wie C(y), dann:

  • Setzen Sie Klammern um den gesamten Ausdruck - (C(y)) und du wirst bekommen, was du wolltest
  • Diese Aussage macht nichts anderes, als ein temporäres Objekt zu schaffen, das nach Beendigung dieser Anweisung nicht mehr lebt (ich hoffe, das ist es, was Sie vorhatten).

17
2018-04-16 13:14