Hat der unäre + Operator einen praktischen Nutzen?

Lesezeit: 6 Minuten

Hat der unare Operator einen praktischen Nutzen
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.

    – Destruktor

    29. Oktober 2015 um 14:57 Uhr

Hat der unare Operator einen praktischen Nutzen
Peter Becker

char ch="a";
std::cout << ch << '\n';
std::cout << +ch << '\n';

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.

    – Peter Becker

    16. Januar 2013 um 19:32 Uhr

  • Scheint bei mir nicht zu funktionieren — stacked-crooked.com/view?id=235071220bc8ba0e688b4b58051e182d könnten das die seltenen Kodierungen sein?

    – David G

    16. Januar 2013 um 19:34 Uhr


  • @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:

enum MyBitMask {
    Flag1 = 0x1,
    Flag2 = 0x2,
    Flag3 = 0x4,
    Flag4 = 0x8000000
};

inline MyBitMask operator&(MyBitMask x, MyBitMask y) {
    return static_cast<MyBitMask>( +x & +y );
}

inline MyBitMask operator|(MyBitMask x, MyBitMask y) {
    return static_cast<MyBitMask>( +x | +y );
}

1645630813 258 Hat der unare Operator einen praktischen Nutzen
Gemeinschaft

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.

1645630814 476 Hat der unare Operator einen praktischen Nutzen
Heilige Schwarze Katze

Unter anderem, + wandelt Lambdas in Funktionszeiger um. Normalerweise erfolgt die Konvertierung automatisch, manchmal jedoch nicht.

Dies kompiliert beispielsweise nicht:

std::array arr{
    [](int x){return x*x;},
    [](int x){return x*x*x;},
};

Sie könnten es zum Laufen bringen, indem Sie den Funktionszeigertyp als angeben std::array Vorlagenparameter, oder du könntest einfach das machen:

std::array arr{
    +[](int x){return x*x;},
    +[](int x){return x*x*x;},
};

  • 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


835720cookie-checkHat der unäre + Operator einen praktischen Nutzen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy