Hat der unäre + Operator einen praktischen Nutzen?
Lesezeit: 6 Minuten
Maskierter Mann
War der unäre + Operator nur zur Symmetrie mit dem Unären enthalten - -Operator, oder findet er praktische Verwendung im C++-Code?
Als ich hier suchte, stieß ich auf Was ist der Zweck des unären ‘+’-Operators in C?, aber die einzigen nützlichen Szenarien dort beinhalten Präprozessor-Makros. Das ist gut zu wissen, aber sie scheinen einige weniger häufige Situationen zu sein und beinhalten Makros. Gibt es Anwendungsfälle mit häufigerem C++-Code?
Mathematisch? Nein. Aber es könnte eine Verwendung beim Überladen von Operatoren mit Klassen finden.
– Annäherung an DarknessFish
16. Januar 2013 um 19:05 Uhr
@ValekHalfHeart: Ja, aber jede Überladung, die etwas anderes bewirkt return *this; wird als Missbrauch angesehen.
– rodrigo
16. Januar 2013 um 19:09 Uhr
@rodrigo Könnte aber noch für eine Nebenwirkung sorgen this, nicht wahr? Ob das ein gutes oder sinnvolles DSL-Design ist, ist eine andere Frage.
– πάντα ῥεῖ
16. Januar 2013 um 19:12 Uhr
@ArneMertz: So schön Boost.Spirit auch ist, es ist sicherlich ein Sprachmissbrauch. Nicht, dass es einen Vorteil hätte, aber das Überladen von Operatoren wurde nicht dafür entwickelt, um solche Dinge zu tun, wie es offensichtlich ist, wenn Sie erkennen, dass Sie die Operatorpriorität nicht ändern können und Ihre ausgefallenen neuen Bedeutungen für alte Operatoren etwas locker sind (cout << a & b;jeder?).
– rodrigo
16. Januar 2013 um 19:18 Uhr
@ApproachingDarknessFish: Es könnte eine Verwendung beim Überladen von Operatoren mit Klassen finden. kannst du es anhand eines beispiels erklären.
Die erste Einfügung schreibt das Zeichen a zu cout. Die zweite Einfügung schreibt den numerischen Wert von ch zu cout. Aber das ist ein bisschen obskur; Es verlässt sich darauf, dass der Compiler integrale Beförderungen für die anwendet + Operator.
Ist der numerische Wert sein ASCII-Äquivalent?
– David G
16. Januar 2013 um 19:26 Uhr
@David – mit einem Compiler, der ASCII verwendet, ja. Für andere Kodierungen (selten), nein.
@David – weiß nicht, was mit deinem Programm los ist, aber 104 ist der ASCII-Code für ‘h’. Oh, Entschuldigung, ich sehe, dass mein Code einen Fehler enthält, den ich gerade behoben habe. Hoffe das hat dich nicht zu sehr verwirrt.
– Peter Becker
16. Januar 2013 um 19:56 Uhr
Symmetrie mit unär - ist nicht völlig nutzlos; es kann zur Hervorhebung verwendet werden:
const int foo = -1;
const int bar = +1;
Und ein überladen einstellig + kann verwendet werden, um eine Operation zu bezeichnen, die dasselbe ergibt logisch value als Operand, während einige nicht triviale Berechnungen durchgeführt werden. (Ich habe gesehen, dass dies für Typkonvertierungen in Ada durchgeführt wurde, was unäre erlaubt +, aber keine Konvertierungen, um überladen zu werden.) Ich habe kein gutes C++-Beispiel zur Hand, und man könnte argumentieren, dass es schlechter Stil wäre. (Andererseits habe ich viele Gerüchte über Überlastung gesehen <<.)
Wie für warum C++ hat es, es dient wahrscheinlich hauptsächlich der Konsistenz mit C, das es mit dem ANSI-Standard von 1989 hinzugefügt hat. Die C Begründung sagt nur:
Unäres Plus wurde vom C89-Komitee aus mehreren Implementierungen übernommen, um die Symmetrie mit unärem Minus zu gewährleisten.
Wenn Sie sich ausdrücklich von einer Zahlenwertsemantik für eine Klasse fernhalten, irgendein Das Überladen von Operatoren ist klar, nicht “das zu tun, was die ints tun”. In diesem Fall kann das unäre Plus jede Bedeutung bekommen und viel mehr tun, als nur zurückzukehren *this
Prominentes Beispiel: Das einfache Plus von Boost.Spirit für die eingebetteten EBNFs Kleene Plus generiert eine Parser-Regel, die ihr Argument (ebenfalls eine Parser-Regel) einmal oder mehrmals übereinstimmen lässt.
Ich wünschte, wir könnten überladen @, $und # zu.
– Muhende Ente
16. Januar 2013 um 21:58 Uhr
@MooingDuck Und wenn Sie schon dabei sind, können wir unsere eigenen Operatoren aus einer beliebigen Kombination von erstellen +-*/%=!<>~^|&*.[]()@#$?
– Schwarzlichtscheinen
27. Februar 2013 um 21:12 Uhr
Die meisten davon würden das Parsen mehrdeutig machen. Wenn der Compiler sieht a+-bsind das die Builtins oder eine Benutzerüberladung?
– Muhende Ente
27. Februar 2013 um 21:40 Uhr
@MooingDuck Es ist eine Überladung, wenn eine solche Überladung vorhanden ist; sonst ist es a + (-b). 😀
– Schwarzlichtscheinen
27. Februar 2013 um 22:42 Uhr
Das Unäre + Operator verwandelt einen lvalue in einen rvalue:
struct A {
static const int value = 1;
};
// ...
int x = std::min(0, A::value);
Oh nein! Dieser Code wird nicht verlinkt, weil jemand vergessen hat, ihn zu definieren (sowie zu deklarieren) A::value. std::min nimmt seine Argumente als Referenz so A::value muss eine Adresse haben, damit eine Referenz daran gebunden werden kann (technisch gesehen besagt die Eine-Definitions-Regel, dass sie genau einmal im Programm definiert werden muss).
Macht nichts, unäres Plus zur Rettung:
int x = std::min(0, +A::value);
Das unäre Plus erstellt ein temporäres mit demselben Wert, und die Referenz bindet an das temporäre, sodass wir die fehlende Definition umgehen können.
Das brauchen Sie nicht oft, aber es ist eine praktische Anwendung des unären Plus-Operators.
Unary + wendet integrale Beförderungen an. Die Antwort von @PeteBecker zeigt einen Weg, der nützlich sein kann.
Beachten Sie außerdem, dass ein Aufzählungstyp ohne Bereichseinschränkung zu einem ganzzahligen Typ hochgestuft wird, der alle Werte in darstellen kann enum. Also in C++03, auch ohne C++11’s std::underlying_type<T>du könntest es tun:
Ein bisschen spät, aber hier ist eine sehr verdrehte Verwendung, über die ich gestolpert bin. Anscheinend die + -Operator kann nützlich sein (wenn auch vielleicht nicht unbedingt erforderlich), wenn Sie Sicherheitsvorkehrungen für die Möglichkeit entwerfen, auf leere Präprozessor-Token zu stoßen. In diesem Beitrag finden Sie eine ausführlichere Diskussion.
Das ist praktisch, aber keineswegs angenehm.
Heilige Schwarze Katze
Unter anderem, + wandelt Lambdas in Funktionszeiger um. Normalerweise erfolgt die Konvertierung automatisch, manchmal jedoch nicht.
Gibt es einen Grund, das Überladene zu bevorzugen? operator+ Funktion vorbei operator* für diesen speziellen Zweck? Ich verstehe nicht warum operator+ wird als die intuitivere Option angesehen, wenn ein Funktionszeiger gewünscht wird.
– 303
13. August 2021 um 17:20 Uhr
@303 Interessant, das ist mir nie in den Sinn gekommen * arbeitete auch hier. Aber keiner von ihnen ist überlastet. + sieht für mich intuitiver aus, weil es nur die Konvertierung durchführt und sonst nichts. Während * führt die Konvertierung in einen Zeiger durch, dereferenziert dann den Zeiger und das Ergebnis wird dann implizit zurück in einen Zeiger konvertiert (es sei denn, Sie benötigen wirklich einen Verweis auf die Funktion).
– HolyBlackCat
13. August 2021 um 17:28 Uhr
8357200cookie-checkHat der unäre + Operator einen praktischen Nutzen?yes
Mathematisch? Nein. Aber es könnte eine Verwendung beim Überladen von Operatoren mit Klassen finden.
– Annäherung an DarknessFish
16. Januar 2013 um 19:05 Uhr
@ValekHalfHeart: Ja, aber jede Überladung, die etwas anderes bewirkt
return *this;
wird als Missbrauch angesehen.– rodrigo
16. Januar 2013 um 19:09 Uhr
@rodrigo Könnte aber noch für eine Nebenwirkung sorgen
this
, nicht wahr? Ob das ein gutes oder sinnvolles DSL-Design ist, ist eine andere Frage.– πάντα ῥεῖ
16. Januar 2013 um 19:12 Uhr
@ArneMertz: So schön Boost.Spirit auch ist, es ist sicherlich ein Sprachmissbrauch. Nicht, dass es einen Vorteil hätte, aber das Überladen von Operatoren wurde nicht dafür entwickelt, um solche Dinge zu tun, wie es offensichtlich ist, wenn Sie erkennen, dass Sie die Operatorpriorität nicht ändern können und Ihre ausgefallenen neuen Bedeutungen für alte Operatoren etwas locker sind (
cout << a & b;
jeder?).– rodrigo
16. Januar 2013 um 19:18 Uhr
@ApproachingDarknessFish: Es könnte eine Verwendung beim Überladen von Operatoren mit Klassen finden. kannst du es anhand eines beispiels erklären.
– Destruktor
29. Oktober 2015 um 14:57 Uhr