Incrementando em C ++ – Quando usar x ++ ou ++ x?

Atualmente estou aprendendo C ++ e aprendi sobre o incremento há um tempo atrás. Eu sei que você pode usar “++ x” para fazer a incremento antes e “x ++” para fazer isso depois.

Ainda assim, eu realmente não sei quando usar qualquer um dos dois … Eu nunca usei “++ x” e as coisas sempre funcionaram bem até agora – então, quando devo usá-lo?

Exemplo: Em um loop for, quando é preferível usar “++ x”?

Além disso, alguém poderia explicar exatamente como as diferentes incrementações (ou decrementações) funcionam? Eu realmente apreciaria isto.

Não é uma questão de preferência, mas de lógica.

x++ incrementa o valor da variável x depois de processar a declaração atual.

++x incrementa o valor da variável x antes de processar a declaração atual.

Então, apenas decida sobre a lógica que você escreve.

x += ++i incrementará i e adicionará i + 1 a x. x += i++ adicionará i a x e incrementará i.

Scott Meyers diz para você preferir o prefixo, exceto nas ocasiões em que a lógica ditaria que o postfix é apropriado.

“Mais eficaz C ++” item # 6 – isso é autoridade suficiente para mim.

Para aqueles que não possuem o livro, aqui estão as citações pertinentes. Da página 32:

Desde seus dias como programador C, você pode lembrar que a forma de prefixo do operador de incremento às vezes é chamada de “incremento e busca”, enquanto o formulário de postfix é conhecido como “busca e incremento”. As duas frases são importantes para lembrar, porque todas elas são apenas especificações formais …

E na página 34:

Se você é do tipo que se preocupa com a eficiência, provavelmente entrou em crise quando viu pela primeira vez a function de incremento do postfix. Essa function tem que criar um object temporário para seu valor de retorno e a implementação acima também cria um object temporário explícito que deve ser construído e destruído. A function de incremento de prefixo não tem tais temporárias …

De cppreference ao incrementar iteradores:

Você deve preferir o operador de pré-incremento (++ iter) ao operador de pós-incremento (iter ++) se não for usar o valor antigo. O pós-incremento é geralmente implementado da seguinte forma:

  Iter operator++(int) { Iter tmp(*this); // store the old value in a temporary object ++*this; // call pre-increment return tmp; // return the old value } 

Obviamente, é menos eficiente que o pré-incremento.

O pré-incremento não gera o object temporário. Isso pode fazer uma diferença significativa se seu object é caro para criar.

Eu só quero notar que o código genired é offen o mesmo se você usar pré / pós-incremento onde a semântica (de pré / post) não importa.

exemplo:

pre.cpp:

 #include  int main() { int i = 13; i++; for (; i < 42; i++) { std::cout << i << std::endl; } } 

post.cpp:

 #include  int main() { int i = 13; ++i; for (; i < 42; ++i) { std::cout << i << std::endl; } } 

_

 $> g++ -S pre.cpp $> g++ -S post.cpp $> diff pre.s post.s 1c1 < .file "pre.cpp" --- > .file "post.cpp" 

O mais importante a ter em mente, imo, é que o x ++ precisa retornar o valor antes que o incremento realmente tenha ocorrido – portanto, ele precisa fazer uma cópia temporária do object (pré-incremento). Isso é menos eficiente que ++ x, que é incrementado no local e retornado.

Outra coisa que vale a pena mencionar, porém, é que a maioria dos compiladores será capaz de otimizar essas coisas desnecessárias quando possível, por exemplo, ambas as opções levarão ao mesmo código aqui:

 for (int i(0);i<10;++i) for (int i(0);i<10;i++) 

Concordo com o @BeowulfOF, embora, para maior clareza, eu sempre defenda a divisão das declarações para que a lógica seja absolutamente clara, ou seja:

 i++; x += i; 

ou

 x += i; i++; 

Então, minha resposta é se você escrever um código claro, então isso raramente deve ser importante (e se isso importa, então seu código provavelmente não está claro o suficiente).

Só queria re-enfatizar que ++ x deve ser mais rápido que x ++, (especialmente se x for um object de algum tipo arbitrário), então a menos que seja necessário por razões lógicas, ++ x deve ser usado.

Você explicou a diferença corretamente. Isso só depende se você quiser x para incrementar antes de cada execução através de um loop, ou depois disso. Depende da lógica do seu programa, o que é apropriado.

Uma diferença importante ao lidar com STL-Iterators (que também implementam esses operadores) é que ela cria uma cópia do object para o qual o iterador aponta, em seguida, incrementa e retorna a cópia. ++, por outro lado, faz o incremento primeiro e depois retorna uma referência ao object para o qual o iterador agora aponta. Isso é mais relevante apenas quando cada bit de desempenho é importante ou quando você implementa seu próprio iterador STL.

Editar: corrigido a mistura de notação de prefixo e sufixo

Entender a syntax da linguagem é importante quando se considera a clareza do código. Considere copiar uma cadeia de caracteres, por exemplo, com pós-incremento:

 char a[256] = "Hello world!"; char b[256]; int i = 0; do { b[i] = a[i]; } while (a[i++]); 

Queremos que o loop seja executado através do encontro do caractere zero (que é falso) no final da string. Isso requer testar o valor pré-incremento e também incrementar o índice. Mas não necessariamente nessa ordem – uma maneira de codificar isso com o pré-incremento seria:

 int i = -1; do { ++i; b[i] = a[i]; } while (a[i]); 

É uma questão de gosto que é mais clara e se a máquina tiver um punhado de registros, ambos devem ter um tempo de execução idêntico, mesmo que [i] seja uma function cara ou que tenha efeitos colaterais. Uma diferença significativa pode ser o valor de saída do índice.

A forma postfix de ++, – operator segue a regra use-then-change ,

Formulário de prefixo (++ x, – x) segue a regra change-then-use .

Exemplo 1:

Quando vários valores são colocados em cascata com << using cout , os cálculos (se houver) ocorrem da direita para a esquerda, mas a impressão ocorre da esquerda para a direita, por exemplo, (se val se inicialmente for 10)

  cout<< ++val<<" "<< val++<<" "<< val; 

resultará em

 12 10 10 

Exemplo 2:

No Turbo C ++, se múltiplas ocorrências de ++ ou (em qualquer forma) são encontradas em uma expressão, então primeiramente todos os formulários de prefixo são computados, então a expressão é avaliada e finalmente os formulários de postfix são computados, por exemplo,

 int a=10,b; b=a++ + ++a + ++a + a; cout< 

Sua saída no Turbo C ++ será

 48 13 

Considerando que sua saída no compilador moderno será (porque eles seguem estritamente as regras)

 45 13 
  • Nota: O uso múltiplo de operadores de incremento / decremento na mesma variável em uma expressão não é recomendado. A manipulação / resultados de tais
    expressões variam de compilador para compilador.