O que o operador mais unário faz? Existem várias definições que eu encontrei ( aqui e aqui ), mas ainda não tenho ideia de para que ela seria usada. Parece que não faz nada, mas tem um motivo para isso, certo?
Respostas:
Ele está lá para ser sobrecarregado se você sentir necessidade; para todos os tipos predefinidos, é essencialmente um ambiente autônomo.
Os usos práticos de um operador aritmético unário no-op são bastante limitados e tendem a se relacionar às consequências do uso de um valor em uma expressão aritmética, em vez do próprio operador. Por exemplo, ele pode ser usado para forçar o alargamento de tipos integrais menores para int
, ou garantir que o resultado de uma expressão seja tratado como um rvalue e, portanto, não compatível com um const
parâmetro sem referência. Afirmo, no entanto, que esses usos são mais adequados para codificar golfe do que legibilidade. :-)
int
e resultar em um rvalue são efeitos da expressão -ness, não do próprio operador +.
Na verdade, mais unário faz alguma coisa - até mesmo em C. Ele executa as conversões aritméticas usuais no operando e retorna um novo valor, que pode ser um inteiro de largura maior. Se o valor original era um inteiro sem sinal de largura menor que int
, ele também será alterado para um signed
valor.
Normalmente, isso não é tão importante, mas pode ter um efeito, por isso é não uma boa idéia usar mais unário como uma espécie de "comentário" denotando que um inteiro é positivo. Considere o seguinte 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);
}
Isso exibirá "x é um int".
Portanto, neste exemplo, mais unário criou um novo valor com um tipo e sinalização diferentes .
an integer of greater width
?
Eu vi isso ser usado para maior clareza, para enfatizar o valor positivo como distinto de um valor negativo:
shift(+1);
shift(-1);
Mas esse é um uso muito fraco. A resposta é definitivamente sobrecarregadora.
vec3(+1,-1,-1)
Uma coisa que o unário integrado +
faz é transformar lvalue em rvalue. Por exemplo, você pode fazer isso
int x;
&x;
mas você não pode fazer isso
&+x;
:)
PS "Sobrecarga" definitivamente não é a resposta certa. Unário +
foi herdado de C e não há sobrecarga de operador no nível do usuário em C.
A principal coisa que unário + realiza é a promoção de tipo para um int para tipos de dados menores que o int. Isso pode ser muito útil se você estiver tentando imprimir dados de caracteres usando std::cout
como dados numéricos.
char x = 5;
std::cout << +x << "\n";
é muito diferente de
char x=5;
std::cout << x << "\n";
Também está disponível para sobrecarga, mas na prática sua sobrecarga deve ser quase um NOP.
Se você precisar imprimir o valor numérico de bytes brutos (por exemplo, pequenos números armazenados como char) para depuração ou qualquer outro motivo, unário + pode simplificar o código de impressão. 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 é apenas um exemplo rápido. Tenho certeza de que há outros momentos em que unário + pode ajudar a tratar seus bytes mais como números em vez de como texto.
Um boato histórico. O comitê de padronização do C99 também achou que os usos existentes do plus unário eram bastante raros, conforme evidenciado por considerarem reutilizá-lo para obter outro recurso na linguagem: a inibição da avaliação do tempo de tradução de expressões constantes de ponto flutuante. Consulte a seguinte citação da justificativa C, seção F.7.4:
Uma versão anterior desta especificação permitia a aritmética da constante de tempo de tradução, mas capacitava o operador unário +, quando aplicado a um operando, para inibir a avaliação de tempo de tradução de expressões constantes.
No final, a semântica foi invertida, com a avaliação do tempo de execução aplicada na maioria dos contextos (pelo menos até a regra "como se") e a capacidade de impor a avaliação do tempo de tradução pelo uso de inicializadores estáticos. Observe que a principal diferença está na ocorrência de exceções de ponto flutuante e outras configurações de arredondamento ou precisão de ponto flutuante, quando presentes.
Não muito. O argumento geral para permitir a sobrecarga de operator+()
é que definitivamente existem usos no mundo real para sobrecarga operator-()
, e seria muito estranho (ou assimétrico) se você permitisse a sobrecarga, operator-()
mas não permitisse operator+()
.
Acredito que li esse argumento de Stroustrop pela primeira vez, mas não tenho meus livros comigo para verificá-lo. Eu posso estar errado.
Unary plus estava presente em C, onde não fazia absolutamente nada (muito parecido com a auto
palavra - chave). Para não tê-lo, Stroustrup teria que introduzir uma incompatibilidade gratuita com C.
Uma vez em C ++, era natural permitir uma função de sobrecarga, assim como o menos unário, e Stroustrup poderia tê-la introduzido por esse motivo se já não estivesse lá.
Então, isso não significa nada. Pode ser usado como uma espécie de decoração para fazer as coisas parecerem mais simétricas, usando +1,5 em vez de -1,5 por exemplo. Em C ++, ele pode ser sobrecarregado, mas será confuso se operator+()
fizer alguma coisa. Lembre-se da regra padrão: ao sobrecarregar operadores aritméticos, faça coisas como os int
s.
Se você está procurando um motivo para ele estar ali, encontre algo sobre a história inicial de C. Suspeito que não houve um bom motivo, já que C não foi realmente projetado. Considere a auto
palavra - chave inútil (presumivelmente em contraste com static
, agora sendo reciclada em C ++ 0x), e a entry
palavra - chave, que nunca fez nada (e depois foi omitida em C90). Há um famoso e-mail em que Ritchie ou Kernighan dizem que, quando perceberam que a precedência do operador tinha problemas, já havia três instalações com milhares de linhas de código que eles não queriam quebrar.
entry
: ( stackoverflow.com/q/254395/153285 ). Hoje em dia, se você quiser vários pontos de entrada, basta usar chamadas de cauda e otimização guiada por perfil.
extern volatile int foo;
, um compilador dado a instrução +foo;
seria necessário para realizar uma leitura do endereço indicado em qualquer plataforma onde qualquer meio possa existir para determinar que a leitura ocorreu. Não tenho certeza de que isso seria necessário se a instrução fosse apenas "foo", embora muitos compiladores façam isso como cortesia.
Não posso citar nenhuma fonte para isso, mas entendi que é para promoção explícita de tipo, o que implica conversão de tipo sem perdas. Isso o coloca no topo da hierarquia de conversão,
new_type operator+(old_type)
new_type(old_type)
operator(new_type)(old_type)
new_type operator=(old_type)
Claro, isso é da minha interpretação de uma nota em um dos manuais c / c ++ da Microsoft (realmente antigos) que li há cerca de 15 anos, então aceite-o com cautela.
#include <stdio.h>
int main()
{
unsigned short x = 5;
printf ("%d\n",sizeof(+x));
printf ("%d\n",sizeof(x));
return 0;
}
Conforme mostrado no exemplo acima, o + unário realmente muda o tipo, tamanho 4 e 2, respectivamente. Estranho que a expressão + x seja de fato calculada no tamanho de, achei que não fosse. Talvez seja devido ao fato de sizeof ter a mesma prioridade que o unário +.
Suponho que você possa usá-lo para sempre tornar um número positivo. Basta sobrecarregar o operador + unário para ser abs. Não vale a pena confundir seus colegas desenvolvedores, a menos que você realmente queira ofuscar seu código. Então funcionaria bem.
~
? Não tenho certeza de qual é a sua definição de "oposto", mas suspeito que seja tendenciosa pela experiência do que o positivo unário e o negativo unário fazem atualmente.
EDIT Reescrever completamente, porque eu estava muuuuuuito longe da minha resposta original.
Isso deve permitir que você trate a declaração explícita de seu tipo como um valor positivo (acho que na maioria das operações não matemáticas). Parece que a negação seria mais útil, mas acho que aqui está um exemplo de onde pode fazer a diferença:
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; }
}
}
+
não é tornar um valor positivo, mas deixar seu sinal inalterado.
simplesmente o usado para convencer quais números são positivos
por exemplo;
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})