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?
Risposte:
È 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 int
o per garantire che il risultato di un'espressione venga trattato come un rvalue e quindi non compatibile con un const
parametro non di riferimento. Affermo, tuttavia, che questi usi sono più adatti al golf del codice che alla leggibilità. :-)
int
e ottenere un valore sono effetti dell'espressione -ness, non dell'operatore + stesso.
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 signed
valore.
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.
an integer of greater width
?
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.
vec3(+1,-1,-1)
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.
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::cout
come 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.
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.
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.
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.
Unario plus era presente in C, dove non faceva assolutamente nulla (molto simile alla auto
parola 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 auto
parola chiave inutile (presumibilmente in contrasto con static
, ora riciclata in C ++ 0x) e la entry
parola 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.
entry
: ( stackoverflow.com/q/254395/153285 ). Oggigiorno, se desideri più punti di ingresso, utilizza le chiamate di coda e l'ottimizzazione guidata dal profilo.
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.
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,
new_type operator+(old_type)
new_type(old_type)
operator(new_type)(old_type)
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.
#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 +.
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.
~
? 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.
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; }
}
}
+
non è rendere positivo un valore, ma lasciare invariato il suo segno.
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})