Geben alle C ++ - Operatoren etwas zurück?

83

Alle C ++ - Operatoren, mit denen ich gearbeitet habe, geben etwas zurück, z. B. gibt der +Operator das Ergebnis der Addition zurück.

Geben alle C ++ - Operatoren etwas zurück oder gibt es einige C ++ - Operatoren, die nichts zurückgeben?

user8240761
quelle
7
Das hängt davon ab, wie eng Sie den Begriff "Operator" definieren.
Molbdnilo
12
Dies wird vom Standard nicht erzwungen - Sie können beispielsweise die +=Rückgabe implementieren void, dies wird jedoch nicht empfohlen. Auch Funktionsaufrufbetreiber können zurückkehren voidund dies ist gültig
Mircea Ispas
Hmm. Ich habe die Vermutung, dass der Operator für die Bereichsauflösung ::nichts zurückgibt, aber ich müsste den Standard konsultieren, um sicherzugehen.
Yksisarvinen
2
Wird der Kontext der Frage nur für C ++ - Typen bereitgestellt oder enthält er auch benutzerdefinierte Typen?
Eljay
@ Eljay Nur die von C ++ bereitgestellten Typen.
user8240761

Antworten:

111

Nein, nicht alle Operatoren geben etwas zurück.

Obwohl sie wahrscheinlich nicht genau das sind , woran Sie denken, beachten Sie, dass die Schlüsselwörter deleteund delete[]C ++ tatsächlich Operatoren sind . und sie sind so definiert, dass sie den voidRückgabetyp haben - was bedeutet, dass sie nichts auswerten (was nicht 'etwas' ist).

Aus der Referenz :

void operator delete  ( void* ptr ) noexcept;
void operator delete[]( void* ptr ) noexcept;
Adrian Mole
quelle
13
Ich mag deine Antwort, ich habe die Frage anders gesehen. delete, delete[], throw, (void)x;Gegossen, linken Seite des ,Bedieners, rechten Seite der ,Bedienperson, dass ergibt eine voida, ?:ternäre , die eine verwendet throwfür einen der Arme, dfri ist operator void()(wäre benutzerdefiniert) eingelegt ,眠りネロク's void operator()()(die Benutzer festgelegt werden würde).
Eljay
10
Es ist auch verwirrend, dass der deleteOperator das Objekt zerstört und dann aufruft operator delete. Ergo, der deleteBetreiber und operator deletesind getrennte Dinge :( stackoverflow.com/a/8918942/845092
Mooing Duck
7
Ich bin mir nicht sicher, warum Sie die Löschfunktionen zitieren, wenn Sie über den Löschoperator sprechen. Aber was auch immer.
Deduplikator
4
@MooingDuck Der Lösch Ausdruck das Objekt zerstört, und dann ruft operator delete.
NathanOliver
Zählt das Löschen als Operator durch, ich dachte, ein Objekt ist etwas, das auf ein Objekt wirkt, das übergeben wird? Beim Löschen muss kein Objekt übergeben oder erstellt werden, damit es funktioniert ..... Genau wie printf .....
Yunfei Chen
82

Operatoren von benutzerdefinierten Typen können überlastet werden, um die seltsamsten Dinge zu tun.

Beispielsweise gibt der Operator + das Ergebnis der Addition zurück.

Nicht unbedingt:

#include <iostream>
struct foo {
    int value = 0;
    void operator+(int x) {
        value += x;
    }
};

int main () {
    foo f;
    f + 3;
}

Hier wird dem operator+Element die linke Seite valuehinzugefügt, und sein Rückgabetyp ist ungültig. Dies ist ein erfundenes Beispiel, aber im Allgemeinen ist es nicht ungewöhnlich, etwas von einem benutzerdefinierten Operator nicht zurückzugeben.

Der einzige Operator, der überlastet werden kann und der die Anforderung hat, etwas zurückzugeben, das mir bekannt ist, ist operator->. Es muss entweder einen Rohzeiger oder ein Objekt mit einem zurückgeben operator->.

idclev 463035818
quelle
Witzigerweise gibt es tatsächlich keine Einschränkung für den Rückgabewert überladener Operatoren. So können Bediener alles zurückgeben, was Sie möchten. en.cppreference.com/w/cpp/language/operators
bracco23
5
@ braccor23 operator->ist etwas Besonderes und muss entweder einen Zeiger oder ein Objekt zurückgeben, das eine hat operator->, nicht sicher, ob es andere Ausnahmen gibt
idclev 463035818
1
Ja, das ist die einzige Einschränkung. Nicht einmal bool für Vergleichsoperatoren. Das sieht echt komisch aus.
bracco23
9
@ idclev463035818: Ein vielleicht nützlicheres Beispiel können Ausdrucksvorlagen sein. Sie können beispielsweise eine Matrixbibliothek erstellen, in der operator*(Matrix const& left, Matrix const& right)nicht, Matrixsondern stattdessen zurückgegeben MatrixMulwird. Wenn diese dann in operator+(Matrix const& left, MatrixMul const& right)die Operation eingespeist wird, kann eine fusionierte Multiplikationsaddition erfolgen, die effizienter ist als zuerst zu multiplizieren und dann zu addieren.
Matthieu M.
1
@DarrelHoffman Wenn <<und >>für E / A-Vorgänge überlastet sind, wird erwartet, dass sie den Stream zurückgeben, damit Sie sie kaskadieren können:stream << foo << bar;
Barmar
34

Um nicht zu picken, geben die Operatoren nichts zurück. Sie sind nur lexikalische Elemente, mit denen wir Ausdrücke in der Sprache erstellen. Ausdrücke haben nun Typen und können zu Werten ausgewertet werden, und ich gehe davon aus, dass Sie dies unter Operatoren verstehen, die "Dinge zurückgeben".

Und ja. Es gibt C ++ - Ausdrücke vom Typ void(und werden daher nicht zu einem Wert ausgewertet). Einige sind offensichtlich, andere weniger. Ein schönes Beispiel wäre

throw std::runtime_error()

throwist ein Ausdruck unter der C ++ - Grammatik. Sie können es in anderen Ausdrücken verwenden, beispielsweise im bedingten Ausdruck

return goodStatus() ? getValue() : throw std::runtime_error();

Und die Art eines Wurfausdrucks ist void. Da dies nur dazu führt, dass die Ausführung schnell an eine andere Stelle geht, hat der Ausdruck offensichtlich keinen Wert.

Geschichtenerzähler - Unslander Monica
quelle
21

Keiner der integrierten in C ++ Operatoren zurückkehren etwas. Überladene C ++ - Operatoren geben insofern etwas zurück, als die Operatornotation ein syntaktischer Zucker für einen Funktionsaufruf ist.

Vielmehr bewerten alle Bediener etwas. Das etwas hat einen genau definierten Wert sowie einen Typ . Auch der Funktionsaufrufoperator void operator()(/*params*/)ist ein voidTyp.

Ist beispielsweise +'a'ein intTyp mit dem Wert " 'a'Auf Ihrer Plattform codiert".

Wenn Ihre Frage lautet "Können C ++ - Operatoren einen voidRückgabetyp haben?" dann lautet die Antwort mit Sicherheit ja.

Bathseba
quelle
14
@ idclev463035818: Es ist der Begriff Return, mit dem ich ein Problem habe. Das einzige, was in C ++ etwas zurückgibt, ist eine Funktion. Ausdrücke bewerten etwas.
Bathseba
7
Operatoren von Klassentypen sind Methoden, die etwas zurückgeben
idclev 463035818
4
Dies ist ein wichtiger Punkt. Schlampige Terminologie führt zu Verwirrung. +1.
Pete Becker
3
@supercat - Ihr Kommentar verleumdet eine Menge fleißiger Leute, einschließlich mir. Diejenigen von uns, die den Standard geschrieben haben, haben nie erwartet, dass Compiler-Autoren Details ausfüllen, indem sie andere Compiler abfragen, ob gegenwärtig oder in der Vergangenheit. Ziel des Standards war und ist es, die Syntax und Semantik der Programmiersprache C ++ klar zu definieren. Ja, das Ergebnis ist nicht perfekt. In der neuesten Norm wurden viele Probleme behoben, die in früheren Versionen nicht behoben wurden. Das kommt aus der Erfahrung, Komplikationen zu erkennen, die zu diesem Zeitpunkt einfach nicht gesehen wurden.
Pete Becker
3
@ Peter-ReinstateMonica - hier ist eine stärkere Version. Der Ausdruck I++gibt keinen Wert zurück. Wenn der Typ von iein benutzerdefinierter Typ ist, wird dieser Ausdruck als implementiert operator++. Dies ist eine Funktion, die einen Wert zurückgibt. Sie nennen das "syntaktischen Zucker"; Ich nenne das eine Unterscheidung, die wichtige Konsequenzen hat.
Pete Becker
12

Sie können tatsächlich einen Funktionsaufrufoperator definieren , der nichts zurückgibt. Zum Beispiel:

struct Task {
   void operator()() const;
};
眠 り ネ ロ ク
quelle
17
Sie können fast jeden Operator so definieren, dass er nichts
zurückgibt
7
@ Yksisarvinen, aber zumindest dieser ist möglicherweise nützlich.
Mark Ransom
11

operator void (): Benutzerdefinierte Konvertierungsfunktion in void

Sie können die eigentümliche operator void()Konvertierungsfunktion definieren , bei der der Compiler Sie sogar warnt, dass die Tto- voidKonvertierungsfunktion niemals verwendet wird :

#include <iostream>

struct Foo {
    operator void() { std::cout << "Foo::operator void()!"; }
    // warning: conversion function converting 'Foo' to 
    //          'void' will never be used
};
    
int main() {
    Foo f;
    (void)f;            // nothing
    f.operator void();  // Foo::operator void()!
}

gemäß [class.conv.fct] / 1

[...] Eine Konvertierungsfunktion wird niemals verwendet, um ein (möglicherweise cv-qualifiziertes) Objekt in den (möglicherweise cv-qualifizierten) gleichen Objekttyp (oder einen Verweis darauf) in eine (möglicherweise cv-qualifizierte) Basisklasse zu konvertieren dieses Typs (oder eines Verweises darauf) oder auf (möglicherweise cv-qualifiziert) void. 117

( 117 ) Diese Konvertierungen werden als Standardkonvertierungen zum Zwecke der Überlastungsauflösung ([over.best.ics], [over.ics.ref]) und damit der Initialisierung ([dcl.init]) und expliziten Casts betrachtet. Eine Konvertierung nach voidruft keine Konvertierungsfunktion auf ([expr.static.cast]). Obwohl solche Konvertierungsfunktionen nie direkt aufgerufen wurden, um eine Konvertierung durchzuführen, können sie deklariert und möglicherweise durch einen Aufruf einer virtuellen Konvertierungsfunktion in einer Basisklasse erreicht werden.

Wie oben gezeigt, können Sie es dennoch mit der expliziten .operator void()Syntax aufrufen .

dfrib
quelle
4

Die durch die Sprache definierten (eingebauten) Operatoren sind Token, mit denen verschiedene Arten von Berechnungen durchgeführt werden:

  • Arithmetik (+, -, *, /)
  • Inkrementieren / Dekrementieren (++, -)
  • Zuordnung (=, + =, - =, * =, / =,% =, >> =, << =, & =, ^ =, | =)
  • Logik (!, &&, ||)
  • relational (== ,! =,>, <,> =, <=)
  • bedingt ?
  • Komma

und so weiter. Die Liste kann sehr umfangreich sein.

In Sprachreferenzen wie dieser oder jener wird nicht unbedingt darauf verwiesen, dass etwas zurückgegeben wird, sondern lediglich eine arithmetische oder logische Operation ausgeführt wird , ein Vergleich, durch den eine Variable geändert werden kann usw.

Da diese Operation zu einem bestimmten Wert führt, kann sie vom Operator als "zurückgegeben" interpretiert werden, unterscheidet sich jedoch von einem Funktionsrückgabewert.

Die überladenen Operatoren können andererseits mit einem Rückgabewert eines bestimmten Typs definiert werden, auch wenn dieser ungültig sein kann. Nein, nicht alle Operatoren geben einen Wert in C ++ zurück.

ram0nvaldez
quelle
3

Ich gehe davon aus, dass Sie über Operatorfunktionen und nicht über Operatoren als syntaktische Einheit der Sprache sprechen.

Wenn Sie Operatoren für einen beliebigen Typ überladen, können Sie tatsächlich alles zurückgeben, was Sie möchten.

Dies ist auch sehr sinnvoll, da Operationen wie * oder () manchmal sehr intuitiv ihren Eingabetyp nicht zurückgeben. Stellen Sie sich vor, Sie multiplizieren einen komplexen Zahlentyp mit einem reellen Zahlentyp. Oder ein Operator, der ein Element aus einer Sammlung zurückgibt.

Sie können auch die Operatoren ++ und - überladen, um nichts zurückzugeben, wodurch die extrem fehleranfällige Mischung aus Nebeneffekt und Ausdruckswert in der Standardversion beseitigt wird.

Kafein
quelle
2

Betrachten Sie diese beiden Beispiele hier:

int multiply (int a, int b) {
   return a*b;
}

void multiply_void(int a, int b) {
   cout << a*b;
//or cout << multiply(a,b);
}

Die erste Funktion gibt einen ganzzahligen Wert zurück, der von einer anderen Funktion verwendet werden kann. Der Wert wird zurückgegeben und im Speicher gespeichert, um bei Bedarf verwendet zu werden. Wenn nicht, ist es für den Menschen nicht sichtbar und sitzt einfach glücklich in der Erinnerung.

Die zweite Funktion wird auf dem Standardausgabegerät (normalerweise Konsole) ausgegeben. Der vom Multiplikationsoperator zurückgegebene Wert wird an ein Ausgabegerät übergeben. Die Funktion multiply_void gibt keinen tatsächlichen Wert zurück.

Gokhan Dilek
quelle
0

Alle Operatoren geben etwas zurück. Sie werden Operatoren genannt, weil sie etwas bedienen, daher geben sie etwas zurück. Operatoren, die nichts zurückgeben, können nicht als Operatoren bezeichnet werden. Je nach Situation geben sie entweder einen Wert zurück oder True oder False.

Alby
quelle
0

Die Betreiber selbst geben nicht unbedingt etwas zurück. Funktionsaufrufe geben Werte zurück. Operatoren können zu Werten führen. Bediener können manchmal Funktionen aufrufen. Beispiele beinhalten:

• Der Funktionsaufrufoperator.

• Ein überladener Operator, der in einen Funktionsaufruf umgewandelt wird.

• Der Operator new, der als Teil eines neuen Ausdrucks aufgerufen wird , ist ein Funktionsaufruf.

Mein einziger Zweck bei der Erwähnung von Funktionsaufrufen besteht darin, das Ergebnis im Vergleich zur Rückgabe zu klären. Basierend auf der Betrachtung aller 126 Instanzen von „return“ und der daraus abgeleiteten Wörter in [expr] scheint der Abschnitt das Wort return sorgfältig zu verwenden, um auf Folgendes zu verweisen:

• das Ergebnis eines Funktionsaufrufs

• Aspekte des Kontrollflusses in Bezug auf Coroutinen

OK, das ist genug Pedanterie für Ergebnis und Rückkehr.

Saddam Kamal
quelle
0

C ++ - Operatoren geben etwas zurück oder nicht. Dies hängt davon ab, wie Sie sie verwendet haben. Integrierte C ++ - Operatoren geben einen Wert zurück, bis er erzwungen wird, void zurückzugeben.


quelle