Pergunta

O que faz o operador mais unário fazer? Existem várias definições que eu encontrei ( aqui e aqui ), mas eu ainda não tenho idéia o que seria usado para. Parece que ele não faz nada mas tem ser uma razão para isso, certo?

Foi útil?

Solução

É lá para ser sobrecarregado, se você sentir a necessidade; para todos os tipos predefinidos é essencialmente um-op não.

As utilizações práticas de um operador aritmética unária não-op são bastante limitados, e tendem para se relacionar com as consequências da utilização de um valor de uma expressão aritmética, em vez do próprio operador. Por exemplo, ele pode ser utilizado para forçar o alargamento de tipos integrais menores para int, ou assegurar que o resultado de uma expressão é tratado como um rvalue e, portanto, não é compatível com um parâmetro de referência não const. Sugiro, porém, que esses usos são mais adequadas para golf código de legibilidade. : -)

Outras dicas

Na verdade, unário mais faz fazer algo - mesmo em C. Ele executa o habituais conversões aritméticas no operando e retorna um novo valor, que pode ser um número inteiro de maior largura. Se o valor original é um inteiro sem sinal de menor largura do que int, ele irá ser alterado para um valor signed bem.

Normalmente, isso não é tão importante, mas pode ter um efeito, por isso é não uma boa idéia usar unário mais como uma espécie de "comentário", denotando que é um número inteiro positivo. Considere o seguinte programa em 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);
}

Isto irá exibir "x é um int".

Assim, neste exemplo unário mais criado um novo valor com um tipo diferente e signedness.

De K & R segunda edição:

O unário + é novo com o padrão ANSI. Foi acrescentada por simetria com o unário -.

Eu já vi isso usado para a clareza, para enfatizar o valor positivo como distinto de um valor negativo:

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

Mas isso é um uso muito fraco. A resposta é, definitivamente, a sobrecarga.

Uma coisa que o lvalue built-in + unário que está se transformando em um rvalue. Por exemplo, você pode fazer isso

int x;
&x;

mas você não pode fazer isso

&+x;

:)

P.S. "Sobrecarga" definitivamente não é a resposta certa. + Unário foi herdada de C e não há nenhum operador a nível de usuário sobrecarga no C.

A principal coisa unário + realiza é tipo de promoção para um int para tipos de dados menores do que o int. Isso pode ser bastante útil se você estiver tentando imprimir os dados CHAR usando std::cout como dados numéricos.

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

é muito diferente de

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

Ele também está disponível para a sobrecarga, mas na prática a sua sobrecarga de 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 depurar ou qualquer motivo, unário + pode simplificar o código de impressão. 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

Este é apenas um exemplo rápido. Estou certo 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 normalização C99 também pensei usos existentes de mais unário eram bastante raras, como evidenciado por sua considerando reutilizá-lo para alcançar uma outra característica na língua: inibição da avaliação em tempo de tradução de expressões constantes de ponto flutuante. Consulte a seguinte citação do C Fundamentação, seção F.7.4:

Uma primeira versão desta especificação permitiu-time tradução constante aritmética, mas habilitada o operador + unária, quando aplicado a um operando, para inibir a tradução em tempo avaliação de expressões constantes.

No final, a semântica foram invertidos, com avaliação de tempo de execução aplicadas na maioria dos contextos (pelo menos até o "como se" regra), ea capacidade de aplicar a avaliação em tempo de tradução, o uso de inicializadores estáticos. Note-se que as principais mentiras diferença na ocorrência de exceções de ponto flutuante, e outro ponto flutuante arredondamento ou as configurações de precisão, quando presente.

Não muito. O argumento geral para permitir a sobrecarga de operator+() é que existem usos mundo definitivamente reais para sobrecarregar operator-(), e seria muito estranho (ou assimétrica) se você fosse para permitir a sobrecarga operator-() mas não operator+().

Eu acredito que li pela primeira vez este argumento de Stroustrop, mas eu não tenho meus livros comigo direito de verificar isso. Eu posso estar errado.

além Unário estava presente em C, onde ele não fez absolutamente nada (muito parecido com a palavra-chave auto). A fim de não tê-lo, Stroustrup teria sido obrigado a introduzir uma incompatibilidade gratuita com C.

Uma vez que estava em C ++, era natural para permitir uma função de sobrecarga, assim como menos unário, e Stroustrup poderia ter introduzido por essa razão se não fosse já existe.

Então, isso não significa nada. Ele pode ser usado como como uma espécie de decoração para fazer as coisas parecerem mais simétrica, usando 1,5 como o oposto para -1,5 por exemplo. Em C ++, pode ser sobrecarregado, mas que vai ser confuso se operator+() faz nada. Lembre-se a regra padrão:. Ao sobrecarregar operadores aritméticos, fazer coisas como as ints fazer

Se você está procurando uma razão pela qual ele está lá, encontrar algo sobre a história precoce de C. Eu suspeito que não havia nenhuma boa razão, como C não foi realmente concebido. Considere a palavra-chave inútil auto (presumivelmente em contraste com static, agora está sendo reciclado em C ++ 0x), ea palavra-chave entry, que nunca fez nada (e mais tarde omitido no C90). Há um email famosa em que Ritchie ou Kernighan dizer que, quando perceberam a precedência do operador teve problemas, já havia três instalações com milhares de linhas de código que não queria quebrar.

Eu não posso citar qualquer fonte para isso, mas eu vim a entender que é para promoção de tipo explícito, o que implica a conversão de tipo lossless. Que o coloca no topo da hierarquia de conversão,

  • promoção: new_type operator+(old_type)
  • conversão: new_type(old_type)
  • Elenco: operator(new_type)(old_type)
  • Coerção: new_type operator=(old_type)

É claro, que do de minha interpretação de uma nota em um dos da Microsoft (realmente de idade) C / C ++ manuais que eu li cerca de 15 anos atrás, então levá-la com um grão 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 mostra no exemplo acima, o unária + realmente muda o tipo, tamanho 4 e 2, respectivamente. Estranho que a expressão + x é realmente calculado no sizeof, eu pensei que não era suposto. Talvez seja devido ao fato de que sizeof tem a mesma prioridade que o unário +.

Eu suponho que você poderia usá-lo para sempre fazer um número positivo. Apenas sobrecarregar o operador + unário ser abs. Não realmente a pena confundir seus desenvolvedores companheiros, a menos que você realmente quer apenas para ofuscar seu código. Em seguida, ele iria funcionar muito bem.

Editar Reescrita completamente, porque eu estava waaaayyy off na minha resposta inicial.

Isso deve permitir que você lidar com a declaração explícita do seu tipo como um valor positivo (acho que em operações de maioria não-matemáticos). Parece que a negação seria mais útil, mas acho que aqui está um exemplo de onde ele 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; }
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top