Unterschiedliche Bedeutungen von Klammern in C ++?

8

Ich bin ein wenig verwirrt mit der Interpretation der Klammern durch den Compiler. Kann jemand bitte erklären, was in solchen Kontexten tatsächlich passiert?

Casting: (int)a oder int(a)

Parameterübergabe:

%Vor%

Offensichtlich gibt es viele verschiedene Kontexte, in denen Klammern die Bedeutung oder Interpretation ändern. Kann jemand erklären, was genau hinter dem Vorhang passiert? Wie kann der Compiler in jedem Kontext interpretieren? Gibt es eine allgemeine Richtlinie oder ist es eine spezifische Regel für jeden Fall?

Danke

    
Kiran 19.02.2011, 04:49
quelle

3 Antworten

20

Captain Pedantic zur Rettung!

Wenn Sie

schreiben %Vor%

Dies wird als explizite Typkonvertierung bezeichnet und unterliegt §5.2.3. Der genaue Wortlaut besagt, dass

  

Ein Simple-Type-Specifier (7.1.5), gefolgt von einer in Klammern gesetzten Ausdruckliste, konstruiert einen Wert des angegebenen Typs in der Ausdruckliste. Wenn die Ausdrucksliste ein einzelner Ausdruck ist, ist der Typkonvertierungsausdruck dem definierten Ausdruck ( (5.4)

) äquivalent (definiert und wenn definiert)

(Mein Schwerpunkt). Das bedeutet also, dass

%Vor%

und

%Vor%

sind vollständig identisch. Es liegt an Ihnen zu wählen, welche von denen Sie einfacher zu schreiben finden.

Wie bei Ihrer zweiten Frage, in dem Beispiel, das Sie mit den Templates und dem Array gegeben haben, glaube ich, dass das, was Sie schreiben wollten, ungefähr so ​​war.

%Vor%

Hier ist N sowie T ein Template-Parameter, mit dem Sie jedes beliebige Array übergeben können, während der Compiler N mit der Anzahl der Elemente im Array füllt. Falls dies verwirrend erscheint (was ist T (&)[N] ?), Liegt das daran, dass diese Funktion einen Parameter vom Typ T (&)[N] einnimmt. Um dies ein wenig einfacher zu lesen, geben wir diesem Parameter einen Namen, wie hier gezeigt:

%Vor%

Ich denke, das macht es ein bisschen leichter zu lesen. Aber was bedeutet diese Erklärung?

%Vor%

Dies deklariert eine Variable namens array , die eine Referenz auf ein Array von T s von genau N -Elementen ist. Sie können tatsächlich Referenzen auf Arrays deklarieren, genau wie Sie Zeiger auf Arrays deklarieren können. Dies ist in der Praxis nicht sehr gebräuchlich, aber in diesem speziellen Template-Idiom ist es eine gute Möglichkeit, dass der Compiler die Größe des Arrays für Sie ableitet, während es versucht, das Array mit dem Template-Argument abzugleichen.

Der Grund für die Klammern in diesem Fall ist, dass wenn Sie

schreiben %Vor%

Der Compiler würde dies als "eine Variable mit dem Namen array , die ein Array von N -Objekten ist, parsen, von denen jede ein T& ist. Die C ++ - Spezifikation verbietet jedoch ausdrücklich Arrays von Referenzen, und dies wäre illegal In den Klammern wird dies explizit disqualifiziert, ähnlich wie bei Funktionszeigern - Sie schreiben

%Vor%

statt

%Vor%

Damit der Compiler erkennt, dass * bedeutet, dass functionPointer ein Zeiger und keine Funktion ist, die ein void * zurückgibt.

Wie der Compiler bestimmt, wann Klammern in jeder Hinsicht behandelt werden müssen, sind die Regeln ziemlich komplex und es gibt tatsächlich einige Umstände, unter denen der Compiler Ihren Ausdruck nicht in der beabsichtigten Weise analysiert. Einer dieser Fälle wird umgangssprachlich als "der ärgerlichste Parse" bezeichnet, bei dem der Compiler das, was wie Objektkonstruktion aussieht, als Funktionsprototyp behandelt. Als Beispiel, dieser Code:

%Vor%

Erstellt nicht eine vector<int> namens v , die mit dem Standardkonstruktor initialisiert wurde. Stattdessen behandelt es dies als einen Funktionsprototyp für eine Funktion namens v , die keine Argumente annimmt und ein vector<int> erzeugt! Wenn Sie jedoch schreiben würden

%Vor%

Dann kann der Compiler eindeutig folgern, dass dies eine Deklaration eines vector<int> ist, das 10 als Konstruktorargument übergibt, weil es unmöglich ist, es als Funktionsprototyp zu behandeln. §6.8 und §8.2 der Spezifikation behandeln diese Fälle, indem sie sagen, dass alles, was als eine Deklaration behandelt werden kann, sein wird und alles, was als ein Funktionsprototyp behandelt werden kann, ebenfalls sein wird.

Der Fall von Klammern im Kontext des Arrays (also T (&array)[N] ) wird von einer anderen Logik behandelt, weil Sie in dem Kontext eine Variable deklarieren oder einen Parameter definieren, dessen Typ explizite Klammern erfordert , es kann keine Zweideutigkeit in Bezug auf Ihre Absicht geben, da es aus dem Kontext klar ist, dass Sie einen Typ benennen, um eine Variable zu deklarieren.

Zusammenfassend -

  1. Casts der Form T(value) und (T)value sind identisch.
  2. Die Klammern in T (&array)[N] verhindern, dass der Compiler das & an T anstatt an array wie vorgesehen bindet.
  3. Die besondere Verwendung von Klammern wird normalerweise aus dem Kontext abgeleitet, obwohl einige Probleme zwischen Variablendeklarationen und Funktionsprototypen auftreten können.

Hoffe, das hilft!

    
templatetypedef 19.02.2011, 08:11
quelle
5
  

casting (int) a oder int (a)

(int) a ist eine Besetzung

int (a) ist die Konstruktion eines int, das in den int ctor hineingeht

Ausdrücke werden nach der Vorrangigkeit der Operatoren ausgewertet, und ob der Operator rechts oder links assoziativ ist. Lesen Sie das Operator-Vorrangdiagramm in Ihrem C ++ - Text.

Erhalte eine Kopie des Programms c ++ decl; Es liest C ++ - Ausdrücke und gibt eine englische Sprachausgabe des Ausdrucks aus. Oder lesen Sie diese Erklärung.

    
tpdi 19.02.2011 04:54
quelle
0

Ab C ++ 14 Anhang A, die vollständige Liste der Fälle, in denen Klammern in der Grammatik vorkommen können, lautet:

%Vor%

Beachten Sie Folgendes:

  • Die Präprozessorregeln für if-group und elif-group beziehen sich auf constant-expression .
  • lparen bedeutet ein ( ohne vorangehende Leerzeichen
  • Die Regel für raw-string ist während des Lexings, also werden die ( und ) keine Token.
  • Jede Sequenz gültiger Tokens kann in einer Präprozessorgruppe erscheinen, deren Bedingung zu false ausgewertet wird.

In Ihrer Frage verwenden Sie Folgendes:

  • cast-expression: ( type-id ) cast-expression
  • postfix-expression: simple-type-specifier ( expression-list_opt )
  • parameters-and-qualifiers: ( parameter-declaration-clause ) attribute-specifier-seq_opt cv-qualifier-seq_opt ref-qualifier_opt exception-specification_opt
  • noptr-abstract-declarator: ( ptr-abstract-declarator )
o11c 02.06.2016 19:32
quelle