Existe uma diferença dentro ++i
e i++
dentro de um for
loop? É simplesmente uma coisa de sintaxe?
Existe uma diferença dentro ++i
e i++
dentro de um for
loop? É simplesmente uma coisa de sintaxe?
Respostas:
um ++ é conhecido como postfix.
adicione 1 a a, retorna o valor antigo.
++ a é conhecido como prefixo.
adicione 1 a a, retorna o novo valor.
C #:
string[] items = {"a","b","c","d"};
int i = 0;
foreach (string item in items)
{
Console.WriteLine(++i);
}
Console.WriteLine("");
i = 0;
foreach (string item in items)
{
Console.WriteLine(i++);
}
Resultado:
1
2
3
4
0
1
2
3
foreach
e while
loops dependem de qual tipo de incremento você usa. Com loops for como abaixo, não faz diferença, pois você não está usando o valor de retorno de i:
for (int i = 0; i < 5; i++) { Console.Write(i);}
Console.WriteLine("");
for (int i = 0; i < 5; ++i) { Console.Write(i); }
0 1 2 3 4
0 1 2 3 4
Se o valor avaliado for usado, o tipo de incremento se tornará significativo:
int n = 0;
for (int i = 0; n < 5; n = i++) { }
O pré-incremento ++ i incrementa o valor de i e é avaliado para o novo valor incrementado.
int i = 3;
int preIncrementResult = ++i;
Assert( preIncrementResult == 4 );
Assert( i == 4 );
O i ++ pós-incremento incrementa o valor de i e é avaliado como o valor não incrementado original.
int i = 3;
int postIncrementResult = i++;
Assert( postIncrementtResult == 3 );
Assert( i == 4 );
Em C ++, o pré-incremento é geralmente preferido onde você pode usar qualquer um.
Isso ocorre porque, se você usar o pós-incremento, pode ser necessário que o compilador gere um código que crie uma variável temporária extra. Isso ocorre porque os valores anteriores e novos da variável que está sendo incrementada precisam ser mantidos em algum lugar, pois podem ser necessários em outro lugar na expressão que está sendo avaliada.
Portanto, pelo menos em C ++, pode haver uma diferença de desempenho que orienta sua escolha de qual usar.
Isso é principalmente apenas um problema quando a variável que está sendo incrementada é um tipo definido pelo usuário com um operador ++ substituído. Para tipos primitivos (int, etc), não há diferença de desempenho. Mas vale a pena aderir ao operador de pré-incremento como uma diretriz, a menos que o operador pós-incremento seja definitivamente o que é necessário.
Há mais discussões aqui:
https://web.archive.org/web/20170405054235/http://en.allexperts.com/q/C-1040/Increment-operators.htm
No C ++, se você estiver usando STL, poderá usar loops para iteradores. Eles têm principalmente operadores ++ substituídos, portanto, é recomendável seguir o pré-incremento. Porém, os compiladores ficam mais inteligentes o tempo todo, e os mais novos podem executar otimizações que significam que não há diferença de desempenho - especialmente se o tipo que está sendo incrementado for definido em linha no arquivo de cabeçalho (como as implementações STL geralmente são) para que o compilador possa ver como o método é implementado e pode saber quais otimizações são seguras para executar. Mesmo assim, provavelmente ainda vale a pena aderir ao pré-incremento, porque os loops são executados várias vezes e isso significa que uma pequena penalidade de desempenho poderá em breve ser ampliada.
Em outras linguagens como C #, onde o operador ++ não pode ser sobrecarregado, não há diferença de desempenho. Utilizados em um loop para avançar a variável do loop, os operadores de pré e pós incremento são equivalentes.
Correção: sobrecarregar ++ em C # é permitido. Parece, porém, que em comparação com o C ++, no c #, você não pode sobrecarregar as versões pré e pós independentemente. Portanto, suponho que, se o resultado da chamada de ++ em C # não for atribuído a uma variável ou usado como parte de uma expressão complexa, o compilador reduzirá as versões pré e pós do ++ para um código que tenha desempenho equivalente.
Em C # não há diferença quando usado em um loop for .
for (int i = 0; i < 10; i++) { Console.WriteLine(i); }
produz a mesma coisa que
for (int i = 0; i < 10; ++i) { Console.WriteLine(i); }
Como outros já apontaram, quando usado em geral i ++ e ++, tenho uma diferença sutil, mas significativa:
int i = 0;
Console.WriteLine(i++); // Prints 0
int j = 0;
Console.WriteLine(++j); // Prints 1
i ++ lê o valor de i e depois o incrementa.
++ i incrementa o valor de i e o lê.
++i
e i++
executam as mesmas operações na mesma ordem: crie uma cópia temporária de i
; aumente o valor do temp para produzir um novo valor (para não substituir o temp); armazene o novo valor em i
; agora se é ++i
o resultado retornado é o novo valor; se i++
o resultado retornado for a cópia temporária. Resposta mais detalhada aqui: stackoverflow.com/a/3346729/3330348
A questão é:
Existe uma diferença em ++ ie ++ em um loop for?
A resposta é: não .
Por que todas as outras respostas têm que entrar em explicações detalhadas sobre pré e pós incremento, quando isso nem sequer é solicitado?
Este loop for:
for (int i = 0; // Initialization
i < 5; // Condition
i++) // Increment
{
Output(i);
}
Seria traduzir para este código sem usar loops:
int i = 0; // Initialization
loopStart:
if (i < 5) // Condition
{
Output(i);
i++ or ++i; // Increment
goto loopStart;
}
Agora importa se você colocar i++
ou ++i
como incremento aqui? Não, pois o valor de retorno da operação de incremento é insignificante. i
será incrementado APÓS a execução do código que está dentro do corpo do loop for.
Desde que você pergunta sobre a diferença em um loop, eu acho que você quer dizer
for(int i=0; i<10; i++)
...;
Nesse caso, você não tem diferença na maioria dos idiomas: o loop se comporta da mesma maneira, independentemente de você escrever i++
ou ++i
. No C ++, você pode escrever suas próprias versões dos operadores ++ e definir significados separados para eles, se oi
for de um tipo definido pelo usuário (sua própria classe, por exemplo).
A razão pela qual isso não importa acima é porque você não usa o valor de i++
. Outra coisa é quando você faz
for(int i=0, a = 0; i<10; a = i++)
...;
Agora, não é uma diferença, porque, como outros apontam, i++
meios incrementar, mas avaliar ao valor anterior , mas ++i
meios de incremento, mas avaliar ai
(assim seria avaliar para o novo valor). No caso acima, a
é atribuído o valor anterior de i, enquanto i é incrementado.
Como esse código mostra (consulte o MSIL desmembrado nos comentários), o compilador C # 3 não faz distinção entre i ++ e ++ i em um loop for. Se o valor de i ++ ou ++ i estivesse sendo obtido, definitivamente haveria uma diferença (isso foi compilado no Visutal Studio 2008 / Release Build):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PreOrPostIncrement
{
class Program
{
static int SomethingToIncrement;
static void Main(string[] args)
{
PreIncrement(1000);
PostIncrement(1000);
Console.WriteLine("SomethingToIncrement={0}", SomethingToIncrement);
}
static void PreIncrement(int count)
{
/*
.method private hidebysig static void PreIncrement(int32 count) cil managed
{
// Code size 25 (0x19)
.maxstack 2
.locals init ([0] int32 i)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: br.s IL_0014
IL_0004: ldsfld int32 PreOrPostIncrement.Program::SomethingToIncrement
IL_0009: ldc.i4.1
IL_000a: add
IL_000b: stsfld int32 PreOrPostIncrement.Program::SomethingToIncrement
IL_0010: ldloc.0
IL_0011: ldc.i4.1
IL_0012: add
IL_0013: stloc.0
IL_0014: ldloc.0
IL_0015: ldarg.0
IL_0016: blt.s IL_0004
IL_0018: ret
} // end of method Program::PreIncrement
*/
for (int i = 0; i < count; ++i)
{
++SomethingToIncrement;
}
}
static void PostIncrement(int count)
{
/*
.method private hidebysig static void PostIncrement(int32 count) cil managed
{
// Code size 25 (0x19)
.maxstack 2
.locals init ([0] int32 i)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: br.s IL_0014
IL_0004: ldsfld int32 PreOrPostIncrement.Program::SomethingToIncrement
IL_0009: ldc.i4.1
IL_000a: add
IL_000b: stsfld int32 PreOrPostIncrement.Program::SomethingToIncrement
IL_0010: ldloc.0
IL_0011: ldc.i4.1
IL_0012: add
IL_0013: stloc.0
IL_0014: ldloc.0
IL_0015: ldarg.0
IL_0016: blt.s IL_0004
IL_0018: ret
} // end of method Program::PostIncrement
*/
for (int i = 0; i < count; i++)
{
SomethingToIncrement++;
}
}
}
}
Um (++ i) é pré-incremento, um (i ++) é pós-incremento. A diferença está em qual valor é retornado imediatamente da expressão.
// Psuedocode
int i = 0;
print i++; // Prints 0
print i; // Prints 1
int j = 0;
print ++j; // Prints 1
print j; // Prints 1
Edit: Woops, ignorou completamente o lado do loop das coisas. Não há diferença real nos loops for quando é a parte 'step' (para (...; ...;)), mas pode entrar em jogo em outros casos.
Não há diferença se você não estiver usando o valor após o incremento no loop.
for (int i = 0; i < 4; ++i){
cout<<i;
}
for (int i = 0; i < 4; i++){
cout<<i;
}
Ambos os loops imprimirão 0123.
Mas a diferença ocorre quando você usa o valor após incremento / decremento no seu loop, conforme abaixo:
Loop de pré-incremento:
for (int i = 0,k=0; i < 4; k=++i){
cout<<i<<" ";
cout<<k<<" ";
}
Saída: 0 0 1 1 2 2 3 3
Pós-incremento do loop:
for (int i = 0, k=0; i < 4; k=i++){
cout<<i<<" ";
cout<<k<<" ";
}
Saída: 0 0 1 0 2 1 3 2
Espero que a diferença seja clara ao comparar a saída. O ponto a ser observado aqui é que o incremento / decremento é sempre executado no final do loop for e, portanto, os resultados podem ser explicados.
Aqui está uma amostra de Java e o código de bytes, pós e pré-incremento não mostram diferença no Bytecode:
public class PreOrPostIncrement {
static int somethingToIncrement = 0;
public static void main(String[] args) {
final int rounds = 1000;
postIncrement(rounds);
preIncrement(rounds);
}
private static void postIncrement(final int rounds) {
for (int i = 0; i < rounds; i++) {
somethingToIncrement++;
}
}
private static void preIncrement(final int rounds) {
for (int i = 0; i < rounds; ++i) {
++somethingToIncrement;
}
}
}
E agora para o código de bytes (javap -private -c PreOrPostIncrement):
public class PreOrPostIncrement extends java.lang.Object{
static int somethingToIncrement;
static {};
Code:
0: iconst_0
1: putstatic #10; //Field somethingToIncrement:I
4: return
public PreOrPostIncrement();
Code:
0: aload_0
1: invokespecial #15; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: sipush 1000
3: istore_1
4: sipush 1000
7: invokestatic #21; //Method postIncrement:(I)V
10: sipush 1000
13: invokestatic #25; //Method preIncrement:(I)V
16: return
private static void postIncrement(int);
Code:
0: iconst_0
1: istore_1
2: goto 16
5: getstatic #10; //Field somethingToIncrement:I
8: iconst_1
9: iadd
10: putstatic #10; //Field somethingToIncrement:I
13: iinc 1, 1
16: iload_1
17: iload_0
18: if_icmplt 5
21: return
private static void preIncrement(int);
Code:
0: iconst_0
1: istore_1
2: goto 16
5: getstatic #10; //Field somethingToIncrement:I
8: iconst_1
9: iadd
10: putstatic #10; //Field somethingToIncrement:I
13: iinc 1, 1
16: iload_1
17: iload_0
18: if_icmplt 5
21: return
}
Sim existe. A diferença está no valor de retorno. O valor de retorno de "++ i" será o valor após o incremento de i. O retorno de "i ++" será o valor antes do incremento. Isso significa que o código se parece com o seguinte:
int a = 0;
int b = ++a; // a is incremented and the result after incrementing is saved to b.
int c = a++; // a is incremented again and the result before incremening is saved to c.
Portanto, a seria 2 e bec seriam, cada um, 1.
Eu poderia reescrever o código assim:
int a = 0;
// ++a;
a = a + 1; // incrementing first.
b = a; // setting second.
// a++;
c = a; // setting first.
a = a + 1; // incrementing second.
Não há diferença real nos dois casos ' i
' será incrementado em 1.
Mas há uma diferença quando você o usa em uma expressão, por exemplo:
int i = 1;
int a = ++i;
// i is incremented by one and then assigned to a.
// Both i and a are now 2.
int b = i++;
// i is assigned to b and then incremented by one.
// b is now 2, and i is now 3
Há mais em ++ ie i ++ que loops e diferenças de desempenho. ++ i retorna um valor l e i ++ retorna um valor r. Com base nisso, há muitas coisas que você pode fazer para (++ i), mas não para (i ++).
1- It is illegal to take the address of post increment result. Compiler won't even allow you.
2- Only constant references to post increment can exist, i.e., of the form const T&.
3- You cannot apply another post increment or decrement to the result of i++, i.e., there is no such thing as I++++. This would be parsed as ( i ++ ) ++ which is illegal.
4- When overloading pre-/post-increment and decrement operators, programmers are encouraged to define post- increment/decrement operators like:
T& operator ++ ( )
{
// logical increment
return *this;
}
const T operator ++ ( int )
{
T temp( *this );
++*this;
return temp;
}
Surpreende-me porque é que as pessoas podem escrever a expressão de incremento no loop for como i ++.
Em um loop for, quando o terceiro componente for uma instrução de incremento simples, como em
for (i=0; i<x; i++)
ou
for (i=0; i<x; ++i)
não há diferença nas execuções resultantes.
Como @ Jon B diz, não há diferença em um loop for.
Mas em um loop while
ou do...while
, você pode encontrar algumas diferenças se estiver fazendo uma comparação com o ++i
oui++
while(i++ < 10) { ... } //compare then increment
while(++i < 10) { ... } //increment then compare
Em javascript, devido ao seguinte i ++ pode ser melhor usar:
var i=1;
alert(i++); // before, 1. current, 1. after, 2.
alert(i); // before, 2. current, 2. after, 2.
alert(++i); // before, 2. current, 3 after, 3.
Enquanto matrizes (acho que todas) e algumas outras funções e chamadas usam 0 como ponto de partida, você teria que definir i como -1 para fazer o loop funcionar com a matriz ao usar ++ i .
Ao usar o i ++, o seguinte valor usará o valor aumentado. Você poderia dizer que o i ++ é o modo como os humanos contam, porque você pode começar com um 0 .
Para entender o que um loop FOR faz
A imagem acima mostra que FOR pode ser convertido em WHILE , pois eles acabam tendo o mesmo código de montagem (pelo menos em gcc). Assim, podemos dividir o FOR em duas partes, para entender o que ele faz.
for (i = 0; i < 5; ++i) {
DoSomethingA();
DoSomethingB();
}
é igual à versão WHILE
i = 0; //first argument (a statement) of for
while (i < 5 /*second argument (a condition) of for*/) {
DoSomethingA();
DoSomethingB();
++i; //third argument (another statement) of for
}
Isso significa que você pode usar FOR como uma versão simples do WHILE :
O primeiro argumento de FOR (int i) é executado, fora, antes do loop.
O terceiro argumento de FOR (i ++ ou ++ i) é executado, dentro, na última linha do loop.
TL: DR: não importa se
i++
ou++i
, sabemos que quando eles são autônomos, eles não fazem diferença, mas um em si mesmos.Na escola, eles geralmente ensinam a maneira i ++, mas também há muitas pessoas que preferem a maneira ++ i devido a várias razões .
NOTA: No passado, o i ++ tinha muito pouco impacto no desempenho, pois não apenas adiciona um por si só, mas também mantém o valor original no registro. Mas, por enquanto, não faz diferença, pois o compilador torna a parte mais a mesma.
Pode haver uma diferença para loops. Esta é a aplicação prática de pós / pré-incremento.
int i = 0;
while(i++ <= 10) {
Console.Write(i);
}
Console.Write(System.Environment.NewLine);
i = 0;
while(++i <= 10) {
Console.Write(i);
}
Console.ReadLine();
Enquanto o primeiro conta até 11 e dá um loop 11 vezes, o segundo não.
Principalmente isso é usado em pouco tempo (x--> 0); - - Faça loop para iterar, por exemplo, todos os elementos de uma matriz (excluindo aqui todas as construções).
Ambos incrementam o número. ++i
é equivalente a i = i + 1
.
i++
e ++i
são muito parecidos, mas não exatamente iguais. Ambos incrementam o número, mas ++i
incrementam o número antes que a expressão atual seja avaliada, enquanto que i++
incrementam o número após a expressão ser avaliada.
int i = 3;
int a = i++; // a = 3, i = 4
int b = ++a; // b = 4, a =
Verifique este link .
Sim, há uma diferença entre ++i
e i++
em um for
loop, embora em casos de uso incomuns; quando uma variável de loop com operador de incremento / decremento é usada no bloco for ou dentro da expressão de teste de loop ou com uma das variáveis de loop . Não, não é simplesmente uma coisa de sintaxe.
Como i
em um código, significa avaliar a expressão i
e o operador não significa uma avaliação, mas apenas uma operação;
++i
significa valor de incremento de i
1 e depois avalia i
,i++
significa avaliar i
e posteriormente incrementar o valor de i
1.Portanto, o que é obtido de cada duas expressões difere porque o que é avaliado difere em cada uma. Tudo igual para --i
ei--
Por exemplo;
let i = 0
i++ // evaluates to value of i, means evaluates to 0, later increments i by 1, i is now 1
0
i
1
++i // increments i by 1, i is now 2, later evaluates to value of i, means evaluates to 2
2
i
2
Em casos de uso incomuns, no entanto, o próximo exemplo parece útil ou não, não importa, mostra uma diferença
for(i=0, j=i; i<10; j=++i){
console.log(j, i)
}
for(i=0, j=i; i<10; j=i++){
console.log(j, i)
}
Para i
tipos definidos pelo usuário, esses operadores podem (mas não devem ) terática semântica significativamente diferente no contexto de um índice de loop, e isso pode (mas não deve) afetar o comportamento do loop descrito.
Além disso, c++
geralmente é mais seguro usar o formulário de pré-incremento ( ++i
) porque é mais facilmente otimizado. (Scott Langham me venceu neste boato . Maldito seja, Scott)
Eu não sei para as outras linguagens, mas em Java ++ i é um incremento de prefixo, o que significa: aumente i em 1 e, em seguida, use o novo valor de i na expressão em que eu reside, e i ++ é um incremento postfix que significa o seguinte : use o valor atual de i na expressão e aumente-o em 1. Exemplo:
public static void main(String [] args){
int a = 3;
int b = 5;
System.out.println(++a);
System.out.println(b++);
System.out.println(b);
} e a saída é:
i ++; ++ i; ambos são semelhantes, pois não são usados em uma expressão.
class A {
public static void main (String []args) {
int j = 0 ;
int k = 0 ;
++j;
k++;
System.out.println(k+" "+j);
}}
prints out : 1 1