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
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:
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
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
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 -
T(value)
und (T)value
sind identisch. T (&array)[N]
verhindern, dass der Compiler das &
an T
anstatt an array
wie vorgesehen bindet. Hoffe, das hilft!
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.
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:
if-group
und elif-group
beziehen sich auf constant-expression
. lparen
bedeutet ein (
ohne vorangehende Leerzeichen raw-string
ist während des Lexings, also werden die (
und )
keine Token. 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 )
Tags und Links c++ parsing compiler-construction parentheses