Qual é a melhor assinatura para operadores aritméticos sobrecarregados em C ++?

StackOverflow https://stackoverflow.com/questions/118630

  •  02-07-2019
  •  | 
  •  

Pergunta

I tinha assumido que a forma canónica para operador +, assumindo que a existência de um operador sobrecarregado + = função de membro, foi assim:

const T operator+(const T& lhs, const T& rhs)
{
    return T(lhs) +=rhs;
}

Mas foi apontado para mim que este trabalho seria também:

const T operator+ (T lhs, const T& rhs)
{
    return lhs+=rhs;
}

Em essência, este transferências formulário de criação da temporária do corpo da implementação da chamada de função.

Parece um pouco estranho ter diferentes tipos para os dois parâmetros, mas há de errado nada com a segunda forma? Existe uma razão para preferir um sobre o outro?

Foi útil?

Solução

Com a questão editado, a primeira forma seria preferível. O compilador mais provável vai otimizar o valor de retorno (você pode verificar isso colocando um ponto de interrupção no construtor para T). A primeira forma também leva os dois parâmetros como const, o que seria mais desejável.

A investigação sobre o tema da valor de retorno otimização , como este destino como um exemplo rápido: http://www.cs.cmu.edu/~gilpin/c++/performance.html

Outras dicas

Eu não tenho certeza se há muita diferença no código gerado para qualquer um.

Entre esses dois, eu (pessoalmente) prefere a primeira forma, uma vez que melhor transmite a intenção. Isto é no que diz respeito a ambos a sua reutilização do operador + = e o idioma de passar tipos templatized por const &.

Eu preferiria a primeira forma para facilitar a leitura.

Eu tive que pensar duas vezes antes de eu vi que o primeiro parâmetro estava sendo copiado. Eu não estava esperando isso. Portanto, assim como ambas as versões são provavelmente tão eficiente que eu iria pegá-los um que é mais fácil de ler.

const T operator+(const T& lhs, const T& rhs)
{
    return T(lhs)+=rhs;
}

Por que não esta se quiser que a concisão?

Meu primeiro pensamento é que a segunda versão pode ser infinitessimally mais rápido do que o primeiro, pois nenhuma referência é empurrado na pilha como um argumento. No entanto, isso seria muito compilador-dependente, e depende, por exemplo, sobre se os executa compilador Named Return Value Optimization ou não.

De qualquer forma, em caso de qualquer dúvida, não escolher para uma pequena ganho de desempenho que pode até não existir e você mais do que provavelmente não vai precisar -. Escolher a versão mais clara, que é a primeira

Na verdade, é preferível

o segundo. Como se afirma no c ++ padrão,

3.7.2 / 2: duração de armazenamento automático

Se um objeto automático chamado tem inicialização ou um destruidor com efeitos colaterais, não será destruídas antes do fim do seu bloco, nem deve ser eliminado como um otimização mesmo que parece ser não utilizado, exceto que um objeto de classe ou sua cópia pode ser eliminado conforme especificada em 12,8.

Isto é, porque um objeto temporário sem nome é criado usando um construtor de cópia, o compilador não pode usar a otimização valor de retorno. Para o segundo caso, no entanto, a otimização valor de retorno sem nome é permitido. Note-se que se os seus implementos compilador chamado otimização valor de retorno, o melhor código é

const T operator+(const T& lhs, const T& rhs)
{
    T temp(lhs);
    temp +=rhs;
    return temp;
}

Eu acho que se você inlined ambos (eu o faria, uma vez que está apenas encaminhamento funções e, presumivelmente, a função de operador + = () é out-of-line), você iria chegar perto de geração de código indistinguíveis. Dito isto, o primeiro é mais canônica. A segunda versão é desnecessariamente "cute".

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top