Sind Klammern um das Ergebnis in einer return-Anweisung von Bedeutung?

79

Gibt es einen Unterschied zwischen diesen beiden Anweisungen innerhalb einer Funktion?

bool returnValue = true;
// Code that does something
return(returnValue);

und das?

bool returnValue = true;
// Code
return returnValue;

Ersteres hat Klammern returnValue.

Jose Villalta
quelle
Vielen Dank, Rob, Sie haben den Geist der Frage erfolgreich erfasst. In Essence habe ich mich gefragt, ob der Compiler etwas Besonderes getan hat (z. B. zuerst versucht hat, den Ausdruck auszuwerten) oder ob er ihn einfach ignoriert hat.
Jose Villalta
1
Es ist schwierig , diese Frage zu beantworten , jede c++ / c. Es wäre gut, die Sprachdefinition genauer zu definieren, aber ich weiß nicht, wie ich das 9 Jahre später beheben kann.
Jonas Stein
Denn Ces gibt ein Duplikat stackoverflow.com/questions/161879/…
Jonas Stein

Antworten:

120

Ab C ++ 14 sind sie häufig.

C ++ 14 fügt einen Randfall hinzu, in dem Klammern um einen Rückgabewert die Semantik ändern können. Dieses Code-Snippet zeigt zwei deklarierte Funktionen. Der einzige Unterschied besteht in Klammern um den Rückgabewert.

int var1 = 42;
decltype(auto) func1() { return var1; } // return type is int, same as decltype(var1)
decltype(auto) func1() { return(var1); } // return type is int&, same as decltype((var1))

In der ersten func1gibt ein intund in der zweiten eine func1zurück int&. Der Unterschied in der Semantik hängt direkt mit den umgebenden Klammern zusammen .

Der autoBezeichner in seiner neuesten Form wurde in C ++ 11 eingeführt. In der C ++ - Sprachspezifikation wird Folgendes beschrieben:

Gibt an, dass der Typ der deklarierten Variablen automatisch von ihrem Initialisierer abgeleitet wird. Gibt für Funktionen an, dass der Rückgabetyp ein nachfolgender Rückgabetyp ist oder aus seinen Rückgabeanweisungen abgeleitet wird (seit C ++ 14).

Außerdem hat C ++ 11 den decltypeSpezifizierer eingeführt, der in der C ++ - Sprachspezifikation beschrieben ist :

Überprüft den deklarierten Typ einer Entität oder fragt den Rückgabetyp eines Ausdrucks ab.

[snip]

  1. Wenn das Argument entweder der nicht in Klammern gesetzte Name eines Objekts / einer Funktion oder ein Mitgliedszugriffsausdruck (object.member oder pointer-> member) ist, gibt der decltype den deklarierten Typ der durch diesen Ausdruck angegebenen Entität an.

  2. Wenn das Argument ein anderer Ausdruck vom Typ T ist, dann

    a) Wenn die Wertekategorie des Ausdrucks xvalue ist, gibt der Dekltyp T && an

    b) Wenn die Wertekategorie des Ausdrucks lvalue ist, gibt der Dekltyp T & an

    c) Andernfalls gibt decltype T an

[snip]

Beachten Sie, dass der Name eines Objekts, wenn er in Klammern steht, zu einem l-Wert-Ausdruck wird. Daher sind decltype (arg) und decltype ((arg)) häufig unterschiedliche Typen.

In C ++ 14 war die Verwendung decltype(auto)für Funktionsrückgabetypen zulässig. In den Originalbeispielen kommt der semantische Unterschied zu Klammern ins Spiel. Wiederholung der ursprünglichen Beispiele:

int var1 = 42;
decltype(auto) func1() { return var1; } // return type is int, same as decltype(var1)
decltype(auto) func1() { return(var1); } // return type is int&, same as decltype((var1))

decltype(auto)Ermöglicht die Ableitung des nachfolgenden Rückgabetyps in der Funktion aus der Entität / dem Ausdruck in der return-Anweisung. In der ersten Version return var1;ist dies effektiv dasselbe wie die Rückgabe des Typs decltype(var1)(ein intRückgabetyp gemäß Regel 1 oben) und im zweiten Fall ist return (var1);es effektiv dasselbe wie decltype((var1))(ein int &Rückgabetyp gemäß Regel 2b).

Die Klammern geben den Rückgabetyp int&anstelle von an int, wodurch sich die Semantik ändert. Moral der Geschichte - "Nicht alle Klammern eines Rückgabetyps sind gleich"

Michael Petch
quelle
Die return-Anweisung ohne Klammern ist immer noch ein lvalue-Ausdruck, oder? Es sei denn, es wird in diesem Szenario als x-Wert behandelt. Können Sie die Wertekategorie der Rückgabe ohne Klammern erklären?
void.pointer
1
Die return-Anweisung gibt einen Lesevorgang des eingegebenen Ausdrucks zurück, dh sie erfasst einen r-Wert aus dem darin enthaltenen Ausdruck und gibt diesen zurück. Wir geben niemals einen Wert zurück. Es ist möglich, dass ein Compiler einen Fehler aufweist, der mit der hier angegebenen Beschreibung und aus den hier angegebenen Gründen übereinstimmt. Dies sollte jedoch niemals return (x);gleichwertig sein return &x;und auch nicht zu einer Rückgabe von führen der Wert von x, aber mit dem Typverweis auf x.
Theodore Murdock
4
Wow, was für ein schreckliches Sprachkonstrukt. Einfach total ... undurchsichtig. Nettes Schreiben, danke.
Paul Sanders
5
C ++ ist eine äußerst interessante Sprache. Aber diese Art von versteckten "Merkmalen" machen mich manchmal verrückt ...
andreee
Unser Code ist voll von diesen unnötigen Klammern. Wir verwenden auch autoziemlich oft. Ändert sich unsere Semantik nie, solange wir uns fernhalten decltype? Ich habe Angst vor unerwartetem Verhalten, wenn wir zur nächsten Compilerversion übergehen, die das nächste Visual Studio enthält.
OneWorld
6

Es gibt keinen Unterschied.

Ein Grund für die Verwendung von Klammern wäre, wenn Sie einen Ausdruck vor der Rückkehr auswerten möchten, in Ihrem Beispiel jedoch keinen Grund. Sehen:

Klammer um Rückgabewerte

zur weiteren Diskussion.

Karl Rosaen
quelle
3
Obwohl diese Klammern auch bei einem komplizierten Ausdruck kein anderes Verhalten verursachen. Sie machen die Bedeutung für menschliche Leser nur (subjektiv!) Offensichtlicher.
Aschepler
@Karl "Ein Grund für die Verwendung von Klammern wäre, wenn Sie einen Ausdruck vor der Rückgabe auswerten möchten." Können Sie ein Beispiel dafür geben?
Chris Middleton
3
@ChrisMiddleton Nein, da die Behauptung hier genauso unsinnig ist wie in diesem Thread. Es gibt keinerlei funktionale Unterschiede zwischen return m * x + cund return (m * x + c)oder return ( (m * x) + c )oder usw. - und es sieht auch nicht besser oder intuitiver aus, wenn Sie mich fragen.
underscore_d
5

Die Klammern im oberen Beispiel sind überflüssig; Sie werden effektiv ignoriert.

Es wäre das gleiche wie so etwas wie ...

int x = (5);

Die Klammern hier werden ebenfalls ignoriert.

James
quelle
Technisch gesehen werden sie nicht ignoriert , sie haben nur keinen Einfluss auf den Wert des Ausdrucks.
John Bode
1
@ John: effektiv ignoriert. :)
James
3
+1… dies ist die einzige Antwort, die besagt, dass die Klammern tatsächlich redundant sind und zeigt, dass ihre Verwendung etwas dumm ist.
Konrad Rudolph
4

AFAIK, nichts ist anders.

In C ++ können Ausdrücke die Form haben: exproder (expr). Letzteres ist also ein Ausdruck mit mehr Typisierung. Weitere Informationen hierzu finden Sie in einer Grammatik (suchen Sie nach "Ausdruck").

David Weiser
quelle
David, danke für den Link. Ich habe die Grammatik in Stroustrups C ++ - Buch, aber (aus Faulheit, denke ich) sehe ich sie mir nicht so oft an, jetzt, wo ich sie in meinem Browser mit einem Lesezeichen versehen habe, kann ich häufiger darauf verweisen.
Jose Villalta
3

Nein, es gibt keinen Unterschied in Ihrem Code.

Elalfer
quelle
3

Ich nehme an, es booist ein Tippfehler, und Sie fragen, ob es einen Unterschied zwischen gibt

return expr;

und

return(expr);

Die Antwort ist nein.

aschepler
quelle
2

Kein Unterschied!!

Menschen verwenden Klammern, wenn es sich um einen komplexen Ausdruck handelt.

Übrigens returnist eine Aussage keine Funktion.

Prasoon Saurav
quelle
2

Nein, es gibt keinen Unterschied zwischen den beiden, obwohl Sie Klammern einfügen können, wenn der Ausdruck dadurch leicht lesbar und klar ist.

sanchit.h
quelle
1
... aber das tut es nie. Warum sollte es? Was ist schwer über einen nicht parästhesierten Ausdruck zu lesen? Das Hinzufügen von Klammern sieht für mich nur nach Unordnung aus. Glauben die Leute, dass returnes sich um einen gierigen Operator handelt, der den Rest return m * x + czurückgeben mund wegwerfen könnte , oder was?
underscore_d
1

Sie verlangsamen den Compiler missbräuchlich!

Das Vorhandensein von Klammern verlangsamt nicht nur die Vorverarbeitungsphase, sondern erzeugt auch einen komplizierteren abstrakten Syntaxbaum: mehr Speicher, mehr Berechnung.


Aus semantischer Sicht? Sie sind genau identisch. Unabhängig davon, ob Klammern vorhanden sind oder nicht return, wird der Ausdruck in der Anweisung vollständig ausgewertet, bevor er zurückgegeben wird.

Matthieu M.
quelle
5
Ich denke genau. Indem der Compiler unnötige Arbeit leistet, um nutzlose Unordnung zu analysieren, nähert er sich ohne guten Grund dem Hitzetod des Universums.
Maxim Egorushkin
4
Wie denkst du über Bitcoins?
Jeremy Nikolai
1

Sie sind identisch. Ich sehe die Syntax in Klammern ziemlich oft und frage immer diejenigen, die sie verwenden: warum ? Und niemand kann antworten, warum sie es benutzen.

Um es auf den Punkt zu bringen: Klammern um zurückkehrende Ausdrücke werden von Personen verwendet, die den Unterschied zwischen funktionsähnlichen Makros und Funktionen nicht ganz verstehen oder die über die Priorität des Operators oder die Reihenfolge der Bewertungsregeln in C verwirrt sind. Es gibt keine Codierung Stil profitieren von der Verwendung von Klammern.

So

return value;

ist korrekter als

return (value)

weil letzteres darauf hindeutet, dass Sie nicht genau wissen, was Sie tun :)

Lundin
quelle
-3

Beide sind in Ihrem Fall gleich.

Zeshan Khan
quelle
MM Könnten Sie bitte Ihren Kommentar erklären?
Zeshan Khan
1
Wenn aist 5dann return a++;und return (a++);(was das gleiche ist) werden beide zurückkehren5
MM
2
Insbesondere gibt postinc / decrement den Vormodifikationswert seines Operanden zurück, und keine Anzahl von Klammern oder anderen erfolglosen Zwangsversuchen wird dies ändern.
underscore_d