Cosa fa l'operatore più unario?


87

Cosa fa l'operatore più unario? Ci sono diverse definizioni che ho trovato ( qui e qui ) ma non ho ancora idea per cosa sarebbe stato utilizzato. Sembra che non faccia nulla ma c'è una ragione per questo, giusto?


3
Penso che il motivo storico sia gravemente sottovalutato.
Wolf

3
Una domanda con tre diversi tag di lingua è piuttosto ambigua / cattiva! Le risposte sono molto diverse per C # (sovraccaricabile) e C (senza sovraccarico) e C ++ (sovraccaricabile ma eredita questo da C e quindi anche le sue proprietà).
legends2k

Vorrei aggiungere un collegamento ai 10 principali difetti di C # di Eric Lippert. Troverai l'operatore unario più nelle menzioni d'onore: informit.com/articles/article.aspx?p=2425867 Fondamentalmente dice che dovrebbe essere rimosso o non dovrebbe essere mai stato aggiunto.
Noel Widmer

Risposte:


57

È lì per essere sovraccaricato se ne senti il ​​bisogno; per tutti i tipi predefiniti è essenzialmente un no-op.

Gli usi pratici di un operatore aritmetico unario non operazionale sono piuttosto limitati e tendono a riguardare le conseguenze dell'uso di un valore in un'espressione aritmetica, piuttosto che l'operatore stesso. Ad esempio, può essere utilizzato per forzare l'ampliamento da tipi integrali più piccoli into per garantire che il risultato di un'espressione venga trattato come un rvalue e quindi non compatibile con un constparametro non di riferimento. Affermo, tuttavia, che questi usi sono più adatti al golf del codice che alla leggibilità. :-)


7
Questo non è effettivamente vero, come indicano diversi esempi di seguito.
jkerian

3
Ok, comprerò che abbia alcuni usi, ma la maggior parte degli usi discussi di seguito si riferiscono al fatto che è un'espressione numerica costruita utilizzando un operatore no-op: ad esempio, promuovere inte ottenere un valore sono effetti dell'espressione -ness, non dell'operatore + stesso.
Jeffrey Hantin,

119

In realtà, il più unario fa qualcosa, anche in C. Esegue le consuete conversioni aritmetiche sull'operando e restituisce un nuovo valore, che può essere un numero intero di larghezza maggiore. Se il valore originale era un numero intero senza segno di larghezza inferiore a int, verrà anch'esso modificato in un signedvalore.

Di solito questo non è così importante, ma può avere un effetto, quindi non è una buona idea usare il più unario come una sorta di "commento" che denota che un numero intero è positivo. Considera il seguente programma C ++:

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);
}

Questo mostrerà "x is an int".

Quindi in questo esempio unario plus ha creato un nuovo valore con un diverso tipo e segnatura.


5
se stai scrivendo codice che produce un determinato risultato quando viene fornito uno short e un int che è uguale al confronto, allora probabilmente hai un problema diverso
Lie Ryan

1
Grazie, è chiaro (nota a margine: in C, non sono riuscito a far funzionare l'esempio, poiché non posso sovraccaricare la funzione foo)
Binarian

cosa vuol dire dire an integer of greater width?
yekanchi

in questo contesto, "larghezza" si riferisce al numero di byte di memoria associati al valore.
giles

41

Dalla seconda edizione di K&R:

L'unario + è nuovo con lo standard ANSI. È stato aggiunto per simmetria con l'unario -.


6
Assolutamente. * Questa è la ragione storica. C ++ ha dovuto adattarlo, quindi ha dovuto affrontare il sovraccarico.
Wolf

38

L'ho visto usato per chiarezza, per enfatizzare il valore positivo come distinto da un valore negativo:

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

Ma questo è un uso piuttosto debole. La risposta è decisamente sovraccarica.


9
L'ho fatto anche io, specialmente quando si tratta di vettori comevec3(+1,-1,-1)
mpen

28

Una cosa che fa l'unario +incorporato è trasformare lvalue in un rvalue. Ad esempio, puoi farlo

int x;
&x;

ma non puoi farlo

&+x;

:)

PS "Sovraccarico" non è sicuramente la risposta giusta. Unario è +stato ereditato da C e non esiste alcun sovraccarico dell'operatore a livello utente in C.


14

La cosa principale che unario + realizza è la promozione del tipo a un int per i tipi di dati più piccoli di int. Questo può essere molto utile se stai cercando di stampare dati char usando std::coutcome dati numerici.

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

è molto diverso da

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

È disponibile anche per il sovraccarico, ma in pratica il tuo sovraccarico dovrebbe essere quasi un NOP.


12

Se mai hai bisogno di stampare il valore numerico dei byte grezzi (ad esempio, piccoli numeri memorizzati come char) per il debug o qualsiasi altra ragione, unario + può semplificare il codice di stampa. Ritenere

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

Questo è solo un rapido esempio. Sono sicuro che ci sono altre volte in cui unario + può aiutarti a trattare i tuoi byte più come numeri invece che come testo.


4

Un bocconcino storico. Il comitato di standardizzazione C99 ha anche ritenuto che gli usi esistenti del plus unario fossero piuttosto rari, come dimostra la loro considerazione di riutilizzarlo per ottenere un'altra caratteristica nella lingua: l'inibizione della valutazione del tempo di traduzione delle espressioni costanti in virgola mobile. Vedere la seguente citazione dal Rationale C, sezione F.7.4:

Una prima versione di questa specifica consentiva l'aritmetica della costante del tempo di traduzione, ma abilitava l'operatore unario +, quando applicato a un operando, per inibire la valutazione del tempo di traduzione delle espressioni costanti.

Alla fine, la semantica è stata invertita, con la valutazione in fase di esecuzione applicata nella maggior parte dei contesti (almeno fino alla regola "come se") e la capacità di imporre la valutazione del tempo di traduzione mediante l'uso di inizializzatori statici. Si noti che la differenza principale sta nella presenza di eccezioni in virgola mobile e altre impostazioni di arrotondamento o precisione in virgola mobile, se presenti.


3

Non tanto. L'argomento generale per consentire il sovraccarico di operator+()è che ci sono sicuramente usi del mondo reale per il sovraccarico operator-(), e sarebbe molto strano (o asimmetrico) se si consentisse il sovraccarico operator-()ma non lo fosse operator+().

Credo di aver letto per la prima volta questo argomento di Stroustrop, ma non ho i miei libri con me per verificarlo. Potrei sbagliarmi.


3

Unario plus era presente in C, dove non faceva assolutamente nulla (molto simile alla autoparola chiave). Per non averlo Stroustrup avrebbe dovuto introdurre un'incompatibilità gratuita con C.

Una volta che era in C ++, era naturale consentire una funzione di sovraccarico, proprio come il meno unario, e Stroustrup avrebbe potuto introdurla per questo motivo se non fosse già lì.

Quindi non significa niente. Può essere usato come una sorta di decorazione per rendere le cose più simmetriche, usando +1,5 come opposto a -1,5 per esempio. In C ++, può essere sovraccaricato, ma creerà confusione se operator+()fa qualcosa. Ricorda la regola standard: quando sovraccarichi gli operatori aritmetici, fai cose comeint s.

Se stai cercando un motivo per cui è lì, trova qualcosa sulla storia antica di C. Sospetto che non ci fosse una buona ragione, poiché C non è stato realmente progettato. Considera la autoparola chiave inutile (presumibilmente in contrasto con static, ora riciclata in C ++ 0x) e la entryparola chiave, che non ha mai fatto nulla (e successivamente omessa in C90). C'è una famosa email in cui Ritchie o Kernighan dicono che, quando si sono resi conto che la precedenza dell'operatore aveva problemi, c'erano già tre installazioni con migliaia di righe di codice che non volevano interrompere.


1
L'unico sovraccarico non aritmetico che ho visto che ha senso era nelle espressioni regolari o nelle grammatiche dove (+ termine) significa uno o più termini. (Che è una sintassi delle espressioni regolari abbastanza standard)
Michael Anderson,

Informazioni su entry: ( stackoverflow.com/q/254395/153285 ). Oggigiorno, se desideri più punti di ingresso, utilizza le chiamate di coda e l'ottimizzazione guidata dal profilo.
Potatoswatter

Credo che anche in C99, dato extern volatile int foo;, un compilatore data l'istruzione +foo;sarebbe tenuto a eseguire una lettura dell'indirizzo indicato su qualsiasi piattaforma in cui potrebbe esistere qualsiasi mezzo per determinare che la lettura ha avuto luogo. Non sono sicuro che sarebbe richiesto se l'istruzione fosse solo "foo", anche se molti compilatori lo faranno come cortesia.
supercat

2

Non posso citare alcuna fonte per questo, ma sono arrivato a capire che è per la promozione del tipo esplicita, che implica una conversione del tipo senza perdite. Questo lo colloca in cima alla gerarchia delle conversioni,

  • Promozione: new_type operator+(old_type)
  • Conversione: new_type(old_type)
  • Cast: operator(new_type)(old_type)
  • Coercizione: new_type operator=(old_type)

Ovviamente, questo deriva dalla mia interpretazione di una nota in uno dei manuali Microsoft (molto vecchi) c / c ++ che ho letto circa 15 anni fa, quindi prendilo con le pinze.


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

Come mostrato nell'esempio sopra, unario + cambia davvero il tipo, la dimensione 4 e 2 rispettivamente. Strano che l'espressione + x sia effettivamente calcolata nella dimensione di, pensavo che non fosse previsto. Forse è dovuto al fatto che sizeof ha la stessa priorità di unario +.


-1

Suppongo che potresti usarlo per rendere sempre un numero positivo. Basta sovraccaricare l'operatore unario + per essere abs. Non vale davvero la pena confondere i tuoi colleghi sviluppatori, a meno che tu non voglia solo offuscare il tuo codice. Allora funzionerebbe bene.


Ciò non renderebbe l'opposto del meno unario che sarebbe fonte di confusione, a meno che non sovraccarichi anche il meno unario per essere gli addominali negativi, il che renderebbe tutti i tipi di cose matematiche
bizzarre

Uhh, sì. Ecco perché ho suggerito di non farlo.
Patrick

1
@ Davy8: Cosa ti fa pensare che il più unario sia attualmente l '"opposto" del meno unario? Qual è l '"opposto" dell'operatore di complemento bit per bit ~? Non sono sicuro di quale sia la tua definizione di "opposto", ma sospetto che sia influenzato dall'esperienza di ciò che unario più e unario meno fanno attualmente.
ndkrempel

-1

EDIT Riscritto completamente, perché ero mooolto fuori posto nella mia risposta originale.

Questo dovrebbe consentirti di gestire la dichiarazione esplicita del tuo tipo come un valore positivo (penso in operazioni prevalentemente non matematiche). Sembra che la negazione sarebbe più utile, ma immagino che questo sia un esempio di dove potrebbe fare la differenza:

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; }
    }
}

A me non sembra un'operazione unaria. Ci vogliono due argomenti (aprile e maggio) in modo che sia binario.
BlueMonkMN

Questo è un vantaggio binario. Più unario è solo "+1" o qualcosa di simile, senza operando sinistro.
Jeffrey Hantin

colpa mia. ho dimenticato il mio CS101. fisso.
Michael Meadows

3
Se trovassi quel tipo di sovraccarico nel codice di produzione, lo contrassegnerei sicuramente come un bug e lo riparerei il prima possibile. La semantica di +non è rendere positivo un valore, ma lasciare invariato il suo segno.
Arturo Torres Sánchez

-1

semplicemente quello usato per convincere quali numeri sono positivi

per esempio;

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})
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.