¿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?
Respuestas:
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 const
parámetro que no sea de referencia. Sin embargo, sostengo que estos usos se adaptan mejor al golf de código que a la legibilidad. :-)
int
operación : por ejemplo, promover y dar como resultado un valor r son efectos de expresión -ness, no del propio operador +.
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 signed
valor.
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 .
an integer of greater width
?
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.
vec3(+1,-1,-1)
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.
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::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 sobrecargas, pero en la práctica su sobrecarga debería ser casi un NOP.
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.
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.
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.
Unary plus estaba presente en C, donde no hizo absolutamente nada (muy parecido a la auto
palabra 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 int
s.
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 auto
palabra clave inútil (presumiblemente en contraste con static
, ahora se recicla en C ++ 0x), y la entry
palabra 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.
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.
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.
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,
new_type operator+(old_type)
new_type(old_type)
operator(new_type)(old_type)
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.
#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 +.
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.
~
? 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.
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; }
}
}
+
no es hacer que un valor sea positivo, sino dejar su signo sin cambios.
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})