Was macht der unäre Plus-Operator?


84

Was macht der unäre Plus-Operator? Es gibt mehrere Definitionen, die ich gefunden habe ( hier und hier ), aber ich habe immer noch keine Ahnung, wofür sie verwendet werden würden. Es scheint, als würde es nichts bewirken, aber es gibt einen Grund dafür, oder?


3
Ich denke, der historische Grund wird stark unterschätzt.
Wolf

3
Eine Frage mit drei verschiedenen Sprach-Tags ist ziemlich vieldeutig / schlecht! Die Antworten sind für C # (überladbar) und C (keine Überladung) und C ++ (überladbar, erbt dies jedoch von C und damit auch von seinen Eigenschaften) sehr unterschiedlich.
Legends2k

Ich möchte einen Link zu Eric Lipperts Top 10-Fehlern von C # hinzufügen. Sie finden den unären Plus-Operator in den ehrenwerten Erwähnungen: informit.com/articles/article.aspx?p=2425867 Er sagt im Grunde, dass er entfernt werden sollte oder niemals hinzugefügt werden sollte.
Noel Widmer

Antworten:


55

Es ist da, um überlastet zu werden, wenn Sie das Bedürfnis haben; Für alle vordefinierten Typen ist es im Wesentlichen ein No-Op.

Die praktischen Verwendungen eines unären arithmetischen No-Op-Operators sind ziemlich begrenzt und beziehen sich eher auf die Konsequenzen der Verwendung eines Werts in einem arithmetischen Ausdruck als auf den Operator selbst. Beispielsweise kann es verwendet werden, um eine Erweiterung von kleineren Integraltypen auf zu erzwingen intoder sicherzustellen, dass das Ergebnis eines Ausdrucks als r-Wert behandelt wird und daher nicht mit einem Nichtreferenzparameter kompatibel constist. Ich behaupte jedoch, dass diese Verwendungen besser zum Codieren von Golf geeignet sind als die Lesbarkeit. :-)


7
Dies ist nicht wirklich wahr, wie einige Beispiele unten zeigen.
Jkerian

3
Okay, ich werde kaufen , dass es einige Anwendungen, aber die meisten der Anwendungen im Folgenden erörterten auf die Tatsache beziehen , dass es ein numerischer Ausdruck ist ein no-op Betreiber gebaut werden: zum Beispiel der Förderung zu intund was zu einem R - Wert sind Effekte des Ausdrucks -ness, nicht vom + Operator selbst.
Jeffrey Hantin

115

Eigentlich unäres Plus hat etwas zu tun - auch in C. Es führt die üblichen arithmetischen Umwandlungen auf dem Operanden und gibt einen neuen Wert, der eine ganze Zahl von größerer Breite sein kann. Wenn der ursprüngliche Wert eine vorzeichenlose Ganzzahl mit einer geringeren Breite als war int, wird er ebenfalls in einen signedWert geändert .

Normalerweise ist dies nicht so wichtig, aber es kann Auswirkungen haben. Daher ist es keine gute Idee, unary plus als eine Art "Kommentar" zu verwenden, der angibt, dass eine Ganzzahl positiv ist. Betrachten Sie das folgende C ++ - Programm:

void foo(unsigned short x)
{
 std::cout << "x is an unsigned short" << std::endl;
}

void foo(int x)
{
 std::cout << "x is an int" << std::endl;
}

int main()
{
 unsigned short x = 5;
 foo(+x);
}

Dies zeigt "x ist ein int" an.

In diesem Beispiel hat unary plus einen neuen Wert mit einem anderen Typ und einer anderen Signatur erstellt.


4
Wenn Sie Code schreiben, der ein gegebenes Ergebnis erzeugt, wenn ein Short und ein Int gegeben werden, die gleich sind, dann haben Sie wahrscheinlich ein anderes Problem
Lie Ryan

1
Danke, das macht es klar (Nebenbemerkung: In C konnte ich das Beispiel nicht zum Laufen bringen, da ich die foo-Funktion nicht überladen kann)
Binarian

Was bedeutet es zu sagen an integer of greater width?
Yekanchi

In diesem Zusammenhang bezieht sich "Breite" auf die Anzahl der dem Wert zugeordneten Speicherbytes.
Giles

40

Aus der zweiten Ausgabe von K & R:

Das unäre + ist neu im ANSI-Standard. Es wurde aus Symmetriegründen mit dem Unären hinzugefügt.


5
Absolut. * Dies ist der historische Grund. C ++ musste es anpassen, damit es mit Überlastung umgehen konnte.
Wolf

36

Ich habe gesehen, dass es der Klarheit halber verwendet wurde, um den positiven Wert im Unterschied zu einem negativen Wert hervorzuheben:

shift(+1);
shift(-1);

Aber das ist eine ziemlich schwache Verwendung. Die Antwort ist definitiv überladen.


8
Ich habe dies auch getan, besonders wenn ich mich mit Vektoren wievec3(+1,-1,-1)
mpen

27

Eine Sache, die der eingebaute +Unary macht, ist, lvalue in einen rvalue zu verwandeln. Dies können Sie beispielsweise tun

int x;
&x;

aber das kannst du nicht machen

&+x;

:) :)

PS "Überladen" ist definitiv nicht die richtige Antwort. Unary +wurde von C geerbt und es gibt keine Überladung von Operatoren auf Benutzerebene in C.


14

Die Hauptsache, die unary + erreicht, ist die Typheraufstufung zu einem int für Datentypen, die kleiner als int sind. Dies kann sehr nützlich sein, wenn Sie versuchen, Zeichendaten std::coutals numerische Daten zu drucken .

char x = 5;
std::cout << +x << "\n";

ist ganz anders als

char x=5;
std::cout << x << "\n";

Es ist auch für Überlastung, aber Ihre Überlastung in der Praxis sollte fast ein NOP sein.


12

Wenn Sie jemals den numerischen Wert von Rohbytes (z. B. kleine Zahlen, die als Zeichen gespeichert sind) zum Debuggen oder aus irgendeinem Grund drucken müssen, kann unary + den Druckcode vereinfachen. Erwägen

char c = 42;
cout << c << endl;           // prints "*\n", not what you want in this case
cout << (int)c << endl;      // prints "42\n", ok
cout << +c << endl;          // prints "42\n", much easier to type

Dies ist nur ein kurzes Beispiel. Ich bin sicher, es gibt andere Zeiten, in denen unary + dazu beitragen kann, Ihre Bytes eher wie Zahlen als wie Text zu behandeln.


4

Ein historischer Leckerbissen. Das C99-Standardisierungskomitee war auch der Ansicht, dass bestehende Verwendungen von unary plus ziemlich selten sind, was durch die Überlegung belegt wird, es wiederzuverwenden, um ein weiteres Merkmal in der Sprache zu erreichen: die Hemmung der Bewertung der Übersetzungszeit von Gleitkommakonstantenausdrücken. Siehe das folgende Zitat aus der C-Begründung, Abschnitt F.7.4:

Eine frühe Version dieser Spezifikation ermöglichte die Arithmetik der Konstanten für die Übersetzungszeit, befähigte jedoch den unären Operator +, wenn er auf einen Operanden angewendet wurde, die Bewertung der Übersetzungszeit für konstante Ausdrücke zu verhindern.

Am Ende wurde die Semantik umgekehrt, wobei die Laufzeitbewertung in den meisten Kontexten erzwungen wurde (zumindest bis zur "Als ob" -Regel) und die Möglichkeit, die Bewertung der Übersetzungszeit mithilfe statischer Initialisierer zu erzwingen. Beachten Sie, dass der Hauptunterschied im Auftreten von Gleitkomma-Ausnahmen und anderen Gleitkomma-Rundungs- oder Präzisionseinstellungen liegt, sofern vorhanden.


3

Nicht viel. Das allgemeine Argument für das Zulassen der Überladung von operator+()ist, dass es definitiv reale Verwendungszwecke für das Überladen gibt operator-(), und es wäre sehr seltsam (oder asymmetrisch), wenn Sie das Überladen zulassen würden, operator-()aber nicht operator+().

Ich glaube, dass ich dieses Argument zuerst von Stroustrop gelesen habe, aber ich habe meine Bücher nicht bei mir, um es zu überprüfen. Ich könnte falsch liegen.


3

Unary Plus war in C vorhanden, wo es absolut nichts tat (ähnlich wie das autoSchlüsselwort). Um es nicht zu haben, hätte Stroustrup eine unbegründete Inkompatibilität mit C einführen müssen.

Sobald es in C ++ war, war es natürlich, eine Überladungsfunktion zuzulassen, genau wie ein unäres Minus, und Stroustrup hätte sie möglicherweise aus diesem Grund eingeführt, wenn sie nicht bereits vorhanden wäre.

Es bedeutet also nichts. Es kann als eine Art Dekoration verwendet werden, um die Dinge symmetrischer aussehen zu lassen, beispielsweise mit +1,5 im Gegensatz zu -1,5. In C ++ kann es überladen sein, aber es wird verwirrend sein, wenn operator+()etwas getan wird. Denken Sie an die Standardregel: Wenn Sie arithmetische Operatoren überladen, tun Sie Dinge wie die ints.

Wenn Sie nach einem Grund suchen, warum es dort ist, finden Sie etwas über die frühe Geschichte von C. Ich vermute, es gab keinen guten Grund, da C nicht wirklich entworfen wurde. Betrachten Sie das nutzlose autoSchlüsselwort (vermutlich im Gegensatz zu dem static, das jetzt in C ++ 0x recycelt wird) und das entrySchlüsselwort, das nie etwas getan hat (und später in C90 weggelassen wurde). Es gibt eine berühmte E-Mail, in der Ritchie oder Kernighan sagen, dass es bereits drei Installationen mit Tausenden von Codezeilen gab, die sie nicht brechen wollten, als sie feststellten, dass die Priorität des Bedieners Probleme hatte.


1
Die einzige nicht-arithmetische Überladung, die ich gesehen habe und die Sinn macht, waren reguläre Ausdrücke oder Grammatiken, bei denen (+ Begriff) ein oder mehrere Tems bedeutet. (Das ist ziemlich Standard Syntax für reguläre Ausdrücke)
Michael Anderson

Info entry: ( stackoverflow.com/q/254395/153285 ). Wenn Sie heutzutage mehrere Einstiegspunkte wünschen, verwenden Sie einfach Tail Calls und profilgesteuerte Optimierung.
Potatoswatter

Ich glaube, dass selbst in C99 extern volatile int foo;ein Compiler, der die Anweisung gegeben hat , einen Lesevorgang +foo;der angegebenen Adresse auf jeder Plattform durchführen müsste, auf der möglicherweise Mittel vorhanden sind, um festzustellen, ob der Lesevorgang stattgefunden hat. Ich bin mir nicht sicher, ob dies erforderlich wäre, wenn die Anweisung nur "foo" wäre, obwohl viele Compiler dies aus Höflichkeit tun werden.
Supercat

2

Ich kann keine Quelle dafür zitieren, aber ich habe verstanden, dass es sich um eine explizite Typwerbung handelt, die eine verlustfreie Typkonvertierung impliziert. Damit steht es an der Spitze der Conversion-Hierarchie.

  • Beförderung: new_type operator+(old_type)
  • Umwandlung: new_type(old_type)
  • Besetzung: operator(new_type)(old_type)
  • Zwang: new_type operator=(old_type)

Das ist natürlich meine Interpretation einer Notiz in einem der Microsoft (wirklich alten) c / c ++ - Handbücher, die ich vor ungefähr 15 Jahren gelesen habe. Nehmen Sie sie also mit einem Körnchen Salz.


1
#include <stdio.h>
int main()
{
    unsigned short x = 5;
    printf ("%d\n",sizeof(+x)); 
    printf ("%d\n",sizeof(x)); 
    return 0;
}

Wie im obigen Beispiel gezeigt, ändert das unäre + wirklich den Typ, die Größe 4 bzw. 2. Seltsam, dass der Ausdruck + x tatsächlich in der Größe von berechnet wird, dachte ich, das sollte nicht. Vielleicht liegt es daran, dass sizeof die gleiche Priorität hat wie das unäre +.


-1

Ich nehme an, Sie könnten es verwenden, um immer eine positive Zahl zu machen. Überladen Sie einfach den unären + Operator, um abs zu sein. Es lohnt sich nicht, Ihre Entwicklerkollegen zu verwirren, es sei denn, Sie möchten Ihren Code wirklich nur verschleiern. Dann würde es gut funktionieren.


Das würde es nicht zum Gegenteil von unärem Minus machen, was verwirrend wäre, es sei denn, Sie überladen auch unäres Minus, um die negativen Bauchmuskeln zu sein, was alle Arten von mathematischen Dingen seltsam machen würde
Davy8

Ähh, ja. Deshalb habe ich vorgeschlagen, es nicht zu tun.
Patrick

1
@ Davy8: Was lässt dich denken, dass unäres Plus derzeit das "Gegenteil" von unärem Minus ist? Was ist das "Gegenteil" des bitweisen Komplementoperators ~? Ich bin mir nicht sicher, was Ihre Definition von "Gegenteil" ist, aber ich vermute, dass sie durch die Erfahrung voreingenommen ist, was unäres Plus und unäres Minus derzeit tun.
Ndkrempel

-1

EDIT komplett neu geschrieben, weil ich in meiner ursprünglichen Antwort waaaayyy war.

Dies sollte es Ihnen ermöglichen, die explizite Deklaration Ihres Typs als positiven Wert zu behandeln (ich denke in meist nicht mathematischen Operationen). Es scheint, dass Negation nützlicher wäre, aber ich denke, hier ist ein Beispiel dafür, wo es einen Unterschied machen könnte:

public struct Acceleration
{
    private readonly decimal rate;
    private readonly Vector vector;

    public Acceleration(decimal rate, Vector vector)
    {
        this.vector = vector;
        this.rate = rate;
    }

    public static Acceleration operator +(Acceleration other)
    {
        if (other.Vector.Z >= 0)
        {
            return other;
        }
        return new Acceleration(other.Rate, new Vector(other.vector.X, other.Vector.Y, -other.vector.Z));
    }

    public static Acceleration operator -(Acceleration other)
    {
        if (other.Vector.Z <= 0)
        {
            return other;
        }
        return new Acceleration(other.Rate, new Vector(other.vector.X, other.Vector.Y, -other.vector.Z));
    }

    public decimal Rate
    {
        get { return rate; }
    }

    public Vector Vector
    {
        get { return vector; }
    }
}

Das sieht für mich nicht nach einer unären Operation aus. Es braucht zwei Argumente (April und Mai), damit das binär ist.
BlueMonkMN

Das ist binäres Plus. Unäres Plus ist nur "+1" oder so, ohne linken Operanden.
Jeffrey Hantin

mein Fehler. habe mein CS101 vergessen. Fest.
Michael Meadows

3
Wenn ich diese Art von Überlastung im Produktionscode finden würde, würde ich sie definitiv als Fehler markieren und so schnell wie möglich beheben. Die Semantik von +besteht nicht darin, einen Wert positiv zu machen, sondern sein Vorzeichen unverändert zu lassen.
Arturo Torres Sánchez

-1

einfach das, um zu überzeugen, welche Zahlen positiv sind

z.B;

int a=10;
System.out.println(+x);// prints 10(that means,that number 10 multiply by +1,{10*+1})

//if we use unary minus

int a=10;
System.out.println(-x);//prints -10(that means,that number 10 multiply by +1,{10*-1})
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.