¿Qué hace el operador unario más?


86

¿Qué hace el operador unario más? Hay varias definiciones que he encontrado ( aquí y aquí ) pero todavía no tengo idea de para qué se usaría. Parece que no hace nada, pero tiene una razón, ¿verdad?


3
Creo que la razón histórica está muy subestimada.
Wolf

3
Una pregunta con tres etiquetas de idioma diferentes es bastante ambigua / mala. Las respuestas son muy diferentes para C # (sobrecarga) y C (sin sobrecarga) y C ++ (sobrecarga pero hereda esto de C y, por lo tanto, también sus propiedades).
legends2k

Me gustaría agregar un enlace a las 10 principales fallas de C # de Eric Lippert. Encontrará el operador unario plus en las menciones honoríficas: informit.com/articles/article.aspx?p=2425867 Básicamente dice que debería eliminarse o nunca debería haberse añadido.
Noel Widmer

Respuestas:


57

Está ahí para sobrecargarse si siente la necesidad; para todos los tipos predefinidos, es esencialmente una operación no operativa.

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 del operador en sí. Por ejemplo, se puede usar para forzar el ensanchamiento de tipos integrales más pequeños a int, o asegurar que el resultado de una expresión se trate como un valor r y, por lo tanto, no sea compatible con un constparámetro que no sea de referencia. Sin embargo, sostengo que estos usos se adaptan mejor al golf de código que a la legibilidad. :-)


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

3
De acuerdo, compraré que tiene algunos usos, pero la mayoría de los usos que se discuten a continuación se relacionan con el hecho de que es una expresión numérica construida con un operador sin intoperación : por ejemplo, promover y dar como resultado un valor r son efectos de expresión -ness, no del propio operador +.
Jeffrey Hantin

118

En realidad, unario plus hace algo, incluso en C. Realiza las conversiones aritméticas habituales en el operando y devuelve un nuevo valor, que puede ser un número entero de mayor ancho. Si el valor original era un número entero sin signo de menor ancho que int, también se cambiará a un signedvalor.

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

Entonces, en este ejemplo, unary plus creó un nuevo valor con un tipo y firma diferente .


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

1
Gracias, eso lo deja claro (nota al margen: en C, no pude hacer que el ejemplo funcione, ya que no puedo sobrecargar la función foo)
Binarian

¿Qué significa decir an integer of greater width?
yekanchi

en este contexto, "ancho" se refiere al número de bytes de almacenamiento asociados con el valor.
giles

41

De la segunda edición de K&R:

El unario + es nuevo con el estándar ANSI. Se agregó por simetría con el unario -.


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

37

Lo he visto usado para mayor claridad, para enfatizar el valor positivo a diferencia de un valor negativo:

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

Pero ese es un uso bastante débil. La respuesta definitivamente es sobrecargada.


8
También he hecho esto, especialmente cuando trato con vectores comovec3(+1,-1,-1)
mpen

28

Una cosa que hace el unario incorporado +es convertir lvalue en un rvalue. Por ejemplo, puedes hacer esto

int x;
&x;

pero no puedes hacer esto

&+x;

:)

PD "Sobrecarga" definitivamente no es la respuesta correcta. Unary +se heredó de C y no hay sobrecarga de operadores a nivel de usuario en C.


14

Lo principal que logra unary + es la promoción de tipos a int para tipos de datos más pequeños que int. Esto puede resultar muy útil si está intentando imprimir datos de caracteres utilizando std::coutcomo 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 sobrecargas, pero en la práctica su sobrecarga debería ser casi un NOP.


12

Si alguna vez necesita imprimir el valor numérico de los bytes sin procesar (por ejemplo, números pequeños almacenados como char) para depurar o por cualquier motivo, unary + puede simplificar el código de impresión. Considerar

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

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


4

Un dato histórico. El comité de estandarización de C99 también pensó que los usos existentes de unario plus eran bastante raros, como lo demuestra su consideración de reutilizarlo para lograr otra característica en el lenguaje: inhibición de la evaluación del tiempo de traducción de expresiones constantes de punto flotante. Consulte la siguiente cita de la justificación C, sección F.7.4:

Una versión anterior de esta especificación permitía la aritmética constante en tiempo de traducción, pero habilitaba al operador unario +, cuando se aplicaba a un operando, para inhibir la evaluación en tiempo de traducción de expresiones constantes.

Al final, la semántica se invirtió, con la evaluación en tiempo de ejecución impuesta en la mayoría de los contextos (al menos hasta la regla "como si") y la capacidad de imponer 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 punto flotante y otros ajustes de precisión o redondeo de punto flotante, cuando están presentes.


3

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

Creo que leí por primera vez 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 (muy parecido a la autopalabra clave). Para no tenerlo, Stroustrup habría tenido que introducir una incompatibilidad gratuita con C.

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

Entonces, 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 lo opuesto a -1.5, por ejemplo. En C ++, puede estar sobrecargado, pero será confuso si operator+()hace algo. Recuerde la regla estándar: cuando sobrecargue los operadores aritméticos, haga cosas como hacen las ints.

Si está buscando una razón por la que está allí, encuentre algo sobre la historia temprana de C. Sospecho que no hubo una buena razón, ya que C no fue realmente diseñado. Considere la autopalabra clave inútil (presumiblemente en contraste con static, ahora se recicla en C ++ 0x), y la entrypalabra clave, 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.


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

Acerca de entry: ( stackoverflow.com/q/254395/153285 ). En estos días, si desea múltiples puntos de entrada, simplemente use llamadas finales y optimización guiada por perfiles.
Potatoswatter

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

2

No puedo citar ninguna fuente para esto, pero he llegado a entender que es para la promoción de tipos explícitos, lo que implica una conversión de tipos sin pérdidas. Eso lo coloca en la parte superior de la jerarquía de conversiones,

  • Promoción: new_type operator+(old_type)
  • Conversión: new_type(old_type)
  • Emitir: operator(new_type)(old_type)
  • Coerción: new_type operator=(old_type)

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


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 se haya calculado en el tamaño de, pensé que no se suponía que fuera así. Quizás se deba al hecho de que sizeof tiene la misma prioridad que el unario +.


-1

Supongo que podrías usarlo para hacer siempre un número positivo. Simplemente sobrecargue el operador unario + para que sea abs. Realmente no vale la pena confundir a sus compañeros desarrolladores, a menos que realmente solo quiera ofuscar su código. Entonces funcionaría muy bien.


Eso no lo haría lo opuesto al menos unario, lo que sería confuso, a menos que también sobrecargue el menos unario para que sean los abdominales negativos, lo que haría que todo tipo de cosas matemáticas
fueran extrañas

Uhh, sí. Por eso sugerí no hacerlo.
Patrick

1
@ Davy8: ¿Qué te hace pensar que el unario más es actualmente el "opuesto" del unario menos? ¿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á sesgado por la experiencia de lo que hacen actualmente el más unario y el menos unario.
ndkrempel

-1

EDITAR Reescribí completamente, porque estaba muuuucho 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í hay un ejemplo de dónde podría marcar la 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; }
    }
}

Eso no me parece una operación unitaria. Se necesitan dos argumentos (abril y mayo), por lo que sería binario.
BlueMonkMN

Eso es un plus binario. Unary plus es simplemente "+1" o algo así, sin operando izquierdo.
Jeffrey Hantin

culpa mía. olvidé mi CS101. fijo.
Michael Meadows

3
Si encuentro ese tipo de sobrecarga en el código de producción, definitivamente lo marcaría como un error y lo arreglaría lo antes posible. La semántica de +no es hacer que un valor sea positivo, sino dejar su signo sin cambios.
Arturo Torres Sánchez

-1

simplemente el que se usa para convencer qué números son positivos

p.ej;

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})
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.