2009-04-07 40 views
61

¿Qué hace el operador unario plus? Hay varias definiciones que he encontrado (here y here) pero todavía no tengo idea de para qué se usaría. Parece que no hace nada pero tiene un motivo, ¿no?¿Qué hace el operador unario plus?

+2

creo que el [razón histórica] (http://stackoverflow.com/a/7611586/2932052) está subestimado gravemente. – Wolf

+2

¡Una pregunta con tres etiquetas de idioma diferentes es bastante ambigua/mala! Las respuestas son muy diferentes para C# (sobrecargable) y C (sin sobrecarga) y C++ (sobrecargable pero hereda esto de C y de ahí sus propiedades también). – legends2k

+0

Me gustaría agregar un enlace a los 10 principales defectos de Cip de Eric Lippert. Se encuentra el operador de suma unaria en el menciones: http://www.informit.com/articles/article.aspx?p=2425867 Básicamente dice que debe ser eliminado o que nunca debería haber sido añadido. –

Respuesta

50

Está allí para ser sobrecargado si sientes la necesidad; para todos los tipos predefinidos es esencialmente un no-op.

Los usos prácticos de un operador aritmético unario no operativo son bastante limitados, y tienden a relacionarse con las consecuencias de usar un valor en una expresión aritmética, en lugar de hacerlo con el operador mismo. Por ejemplo, se puede usar para forzar la ampliación de tipos integrales más pequeños a int, o asegurarse de que el resultado de una expresión se trate como un valor r y, por lo tanto, no sea compatible con un parámetro de referencia que no sea const. Sin embargo, afirmo que estos usos son más adecuados para codificar el golf que la legibilidad. :-)

+3

Esto no es realmente cierto, como indican varios ejemplos a continuación. – jkerian

+3

Está bien, compraré que tiene algunos usos, pero la mayoría de los usos que se analizan a continuación se relacionan con el hecho de que es una expresión numérica construida utilizando un operador no operativo: por ejemplo, promoviendo a 'int' y dando como resultado un valor r son efectos de expresión-ness, no del operador + mismo. –

-1

EDIT Reescribí por completo, porque me quedé sin respuesta en mi respuesta original.

Esto debería permitirle manejar la declaración explícita de su tipo como un valor positivo (creo que en la mayoría de las operaciones no matemáticas). Parece que la negación sería más útil, pero supongo que aquí es un ejemplo de que podría hacer una diferencia:

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

Eso no me parece una operación unaria. Se necesitan dos argumentos (abril y mayo) para que sea binario. – BlueMonkMN

+0

Eso es binario plus. Unario plus es solo "+1" o algo así, sin ningún operando a la izquierda. –

+0

mi mal. Olvidé mi CS101. fijo. –

0

supongo que se podría utilizar para hacer siempre un número positivo. Simplemente sobrecargue el operador unario + para que sea abs. No merece la pena confundir a tus compañeros desarrolladores, a menos que realmente quieras ofuscar tu código. Entonces funcionaría bien.

+0

Eso haría que no fuera lo opuesto al menos unario, lo que sería confuso, a menos que también sobrecargues el negativo unario para que sean los abs negativos, lo que haría que todo tipo de cosas de matemáticas fuesen – Davy8

+0

Uhh, sí. Es por eso que sugerí no hacerlo. – Patrick

+0

@ Davy8: ¿Qué te hace pensar que unary plus es * actualmente * el "opuesto" de unary minus? ¿Cuál es el "opuesto" del operador de complemento bit a bit '~ '? No estoy seguro de cuál es su definición de "opuesto", pero sospecho que está sesgada por la experiencia de lo que unary plus y unary minus hacen actualmente. – ndkrempel

30

que he visto que se usa para mayor claridad, hacer hincapié en el valor positivo a diferencia de un valor negativo:

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

pero eso es un uso bastante débil. La respuesta es definitivamente sobrecarga.

+20

Punto importante +1 (sin juego de palabras) –

+4

He hecho esto también, especialmente cuando se trata de vectores como 'vec3 (+ 1, -1, -1)' – mpen

3

No mucho. El argumento general para permitir la sobrecarga de operator+() es que definitivamente hay usos del mundo real para sobrecargar operator-(), y sería muy extraño (o asimétrico) si permitiera la sobrecarga operator-() pero no operator+().

Creo que primero leí este argumento de Stroustrop, pero no tengo mis libros conmigo para verificarlo. Podría estar equivocado.

3

Unary plus estaba presente en C, donde no hizo absolutamente nada (al igual que la palabra clave auto). Para no tenerlo, Stroustrup debería haber introducido una incompatibilidad gratuita con C.

Una vez que estaba en C++, era natural permitir una función de sobrecarga, al igual que unario menos, y Stroustrup podría haberlo introducido para esa razón si no estaba ya allí.

Por lo tanto, no significa nada. Se puede usar como una especie de decoración para hacer que las cosas se vean más simétricas, usando +1.5 como opuesto a -1.5, por ejemplo. En C++, puede estar sobrecargado, pero va a ser confuso si operator+() hace algo. Recuerde la regla estándar: al sobrecargar operadores aritméticos, haga cosas como int s do.

Si está buscando una razón por la cual está allí, encuentre algo sobre la historia temprana de C. Sospecho que no había una buena razón, ya que C no estaba realmente diseñado. Considere la palabra clave inútil auto (presumiblemente en contraste con static, que ahora se recicla en C++ 0x), y la palabra clave entry, que nunca hizo nada (y luego se omitió en C90). Hay un correo electrónico famoso en el que Ritchie o Kernighan dicen que, cuando se dieron cuenta de que la precedencia del operador tenía problemas, ya había tres instalaciones con miles de líneas de código que no querían romper.

+0

La única sobrecarga no aritmética que he visto tiene sentido en expresiones regulares o gramáticas donde (+ término) significa uno o más términos. (Que es la sintaxis de expresión regular bastante estándar) –

+0

Acerca de 'entry': (http://stackoverflow.com/q/254395/153285). En estos días, si quiere puntos de entrada múltiples, solo use llamadas de cola y optimización guiada por perfil. – Potatoswatter

+0

Creo que incluso en C99, dado 'extern volatile int foo;', se requeriría un compilador con la instrucción '+ foo;' para realizar una lectura de la dirección indicada en cualquier plataforma donde podría existir algún medio para determinar que la lectura tuvo lugar. No estoy seguro de que sea necesario si la declaración fuera solo "foo", aunque muchos compiladores lo harán por cortesía. – supercat

1

No puedo citar ninguna fuente para esto, pero he llegado a entender que es para promoción de tipo explícita, lo que implica la conversión de tipo sin pérdida. Eso lo pone en la parte superior de la jerarquía de la conversión,

  • Promoción:new_type operator+(old_type)
  • Conversión:new_type(old_type)
  • Reparto:operator(new_type)(old_type)
  • coacción:new_type operator=(old_type)

Por supuesto, eso es de mi interpretación de una nota en uno de los manuales microsoft (muy antiguos) c/C++ que leí hace unos 15 años, así que tómalo con un grano de sal.

95

realidad, unario más qué hacer algo - incluso en C. Se lleva a cabo la usual arithmetic conversions en el operando, y devuelve un nuevo valor, que puede ser un entero mayor anchura. Si el valor original era un entero sin signo de menor ancho que int, también se cambiará a un valor signed.

lo general, esto no es tan importante, pero puede tienen un efecto, por lo que es no es una buena idea utilizar unario más como una especie de "comentarios" que denota un número entero positivo. Considere el siguiente programa de 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); 
} 

Esto mostrará "x is an int".

Por lo tanto, en este ejemplo unario plus creó un nuevo valor con un tipo diferente y firmado.

+4

Confirmado: http://codepad.org/RquPlVRJ –

+2

si está escribiendo código que produce un resultado dado cuando se le da un breve y un int que se compara igual, entonces probablemente tenga un problema diferente –

+1

Gracias, eso lo deja en claro (nota al margen : En C, no pude obtener el ejemplo para trabajar, ya que no puedo sobrecargar la función foo) – Binarian

13

Lo principal unario + logra es la promoción tipo a un int para tipos de datos menores que-int. Esto puede ser bastante útil si está intentando imprimir datos de caracteres utilizando std::cout como datos numéricos.

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

es muy diferente de

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

También está disponible para la sobrecarga, pero en la práctica su sobrecarga debería ser casi un NOP.

22

Una cosa que el built-in unary + hace es convertir lvalue en un valor r.Por ejemplo, se puede hacer esto

int x; 
&x; 

pero no se puede hacer esto

&+x; 

:)

P. S. La "sobrecarga" definitivamente no es la respuesta correcta. Unario + fue heredado de C y no hay operador de nivel de usuario la sobrecarga en C.

29

De K segunda edición & R:

El unario + es nuevo con la norma ANSI. Fue agregado por simetría con el unario -.

+1

Absolutamente. *** Esta es la razón histórica. ** C++ tuvo que adaptarlo, por lo que tuvo que lidiar con la sobrecarga. – Wolf

3

un dato histórico. El comité de normalización C99 también pensó usos existentes de unario mas eran bastante raras, como lo demuestra su reutilización teniendo en cuenta que para lograr otra característica en el idioma: inhibición de la evaluación en tiempo traducción de expresiones constantes de punto flotante. Ver la siguiente cita de la C Justificación, sección F.7.4:

Una primera versión de esta especificación mascotas-tiempo de traducción aritmética constante, pero facultado el operador unario +, cuando se aplica a un operando, para inhibir la traducción -time evaluación de expresiones constantes.

Al final, la semántica se invirtieron, con la evaluación en tiempo de ejecución forzada en la mayoría de los contextos (por lo menos hasta el "como si" regla), y la capacidad para hacer cumplir la evaluación en tiempo de traducción mediante el uso de inicializadores estáticos Tenga en cuenta que la principal diferencia radica en la aparición de excepciones de coma flotante y otros ajustes de precisión o redondeo de punto flotante, cuando están presentes.

9

Si alguna vez tiene que imprimir el valor numérico de bytes primas (por ejemplo, pequeños números almacenados como char) para la depuración o la razón que sea, unario + puede simplificar el código de impresión. Considere

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 

Esto es solo un ejemplo rápido. Estoy seguro de que hay otras ocasiones en que unario + puede ayudar a tratar sus bytes más como números en lugar de texto similar.

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

Como se muestra en el ejemplo anterior, el unario + realmente cambia el tipo, tamaño 4 y 2 respectivamente. Es extraño que la expresión + x de hecho se calcule en el tamaño de, pensé que no se suponía que lo hiciera. Tal vez se deba al hecho de que sizeof tiene la misma prioridad que el unario +.

Cuestiones relacionadas