A exatidão do código que você escreve deve nunca depender de uma otimização. Ele deve produzir o resultado correto quando executado na "máquina virtual" C ++ que eles usam na especificação.
No entanto, o que você fala é mais uma questão de eficiência. Seu código funciona melhor se for otimizado com um compilador de otimização de RVO. Tudo bem, por todas as razões apontadas nas outras respostas.
No entanto, se você exigir essa otimização (como, por exemplo, se o construtor de cópias causar falhas no código), agora você está no capricho do compilador.
Acho que o melhor exemplo disso em minha prática é a otimização da chamada de ponta:
int sillyAdd(int a, int b)
{
if (b == 0)
return a;
return sillyAdd(a + 1, b - 1);
}
É um exemplo tolo, mas mostra uma chamada final, em que uma função é chamada recursivamente no final de uma função. A máquina virtual C ++ mostrará que este código funciona corretamente, embora eu possa causar uma pequena confusão quanto a por que eu me incomodei em escrever tal rotina de adição em primeiro lugar. No entanto, nas implementações práticas do C ++, temos uma pilha e um espaço limitado. Se feito de forma pedante, esta função teria que empurrar pelo menos b + 1
de quadros de pilha para a pilha, como faz a sua adição. Se eu quiser calcular sillyAdd(5, 7)
, isso não é grande coisa. Se eu quiser calcular sillyAdd(0, 1000000000)
, posso estar com problemas para causar um StackOverflow (e não o bom tipo ).
No entanto, podemos ver que, quando chegamos à última linha de retorno, terminamos com tudo no quadro de pilha atual. Nós realmente não precisamos manter isso por perto. A otimização da chamada de cauda permite "reutilizar" o quadro de pilha existente para a próxima função. Dessa forma, precisamos apenas de 1 quadro de pilha, em vez de b+1
. (Ainda temos que fazer todas essas adições e subtrações bobas, mas elas não ocupam mais espaço). Na verdade, a otimização transforma o código em:
int sillyAdd(int a, int b)
{
begin:
if (b == 0)
return a;
// return sillyAdd(a + 1, b - 1);
a = a + 1;
b = b - 1;
goto begin;
}
Em alguns idiomas, a otimização da chamada de retorno é explicitamente exigida pela especificação. C ++ é não um desses. Não posso confiar em compiladores C ++ para reconhecer essa oportunidade de otimização de chamada final, a menos que eu vá caso a caso. Com a minha versão do Visual Studio, a versão de lançamento faz a otimização da chamada final, mas a versão de depuração não (por design).
Assim, seria ruim para mim depender de poder calcular sillyAdd(0, 1000000000)
.