C++ 是否有理由跳过for循环的初始化?

C++ 是否有理由跳过for循环的初始化?,c++,performance,for-loop,C++,Performance,For Loop,比如说, int i = 0; for( ; i < 5; ++i ) { doStuff(); } inti=0; 对于(;i

比如说,

int i = 0;
for( ; i < 5; ++i )
{
    doStuff();
}
inti=0;
对于(;i<5;++i)
{
doStuff();
}

for( int i = 0; i < 5; ++i )
{
    doStuff();
}
for(int i=0;i<5;++i)
{
doStuff();
}

我唯一一次看到第一个方法是当要初始化的变量是一个非常长的命名迭代器时。是否有任何性能方面的东西可以使其更为有利?还是仅仅是选择和可读性?

这样做的一个原因是,在循环结束后,您需要知道迭代器/索引的值。这在您的示例中没有真正意义,因为您知道值将是
5
,但有时您事先并不知道这一点。考虑:

int i = 0;
for(; isStillOkay(i); ++i )
{
  doStuff();
}

// now we can use the final value of i for something
通常,您必须这样做的唯一原因是确保迭代器/索引在封闭范围内可用。如果你不需要,你所做的就是污染这个范围。和往常一样,建议是给所有对象提供所需的最小范围

如果您有长类型,我建议您使用
auto
来推断类型。如果您不支持C++11,我建议您使用以下格式:

for (std::some::very_long<type>::name iterator_name = some_big_initializer;
     iterator_name < complicated && condition != iterator_name;
     ++iterator_name)
{
  // ...
}
for(std::some::very_long::name迭代器\u name=some\u big\u初始值设定项;
迭代器名称
这样做的一个原因是,在循环结束后,您需要知道迭代器/索引的值。这在您的示例中没有真正意义,因为您知道值将是
5
,但有时您事先并不知道这一点。考虑:

int i = 0;
for(; isStillOkay(i); ++i )
{
  doStuff();
}

// now we can use the final value of i for something
通常,您必须这样做的唯一原因是确保迭代器/索引在封闭范围内可用。如果你不需要,你所做的就是污染这个范围。和往常一样,建议是给所有对象提供所需的最小范围

如果您有长类型,我建议您使用
auto
来推断类型。如果您不支持C++11,我建议您使用以下格式:

for (std::some::very_long<type>::name iterator_name = some_big_initializer;
     iterator_name < complicated && condition != iterator_name;
     ++iterator_name)
{
  // ...
}
for(std::some::very_long::name迭代器\u name=some\u big\u初始值设定项;
迭代器名称
当您有充分理由进行无限循环时,无需初始化:

bool run(){
    for(;;){
        if(ERROR)
            break;
    }
}

当您有充分理由使用无限循环时,无需初始化:

bool run(){
    for(;;){
        if(ERROR)
            break;
    }
}

如果
i
是一个参数怎么办?用一个不需要的变量污染封闭范围并造成一般混乱。此外,旧的C89标准要求在任何块的开头声明变量,因此第一种方法是唯一的方法。作为C99扩展的一部分,这个约束得到了缓解;对于(i=0;i<5;i++),即在循环外声明它,在循环内初始化它。如果
i
是一个参数,会怎么样?用一个不需要的变量污染封闭范围,并导致一般混乱。此外,旧的C89标准要求在任何块的开头声明变量,因此第一种方法是唯一的方法。作为C99扩展的一部分,这个约束得到了缓解;对于(i=0;i<5;i++),即在循环外部声明它,在循环内部初始化它;对于(i=0;IsStillOk(i);++i){doStuff();}/*现在我们可以将i的最终值用于*/,那么赋值仍然在的
中。谢谢。我看到的代码将它作为第一个方法,但我认为它是为了可读性,因为它是在一个小方法中,并且对最终值没有任何作用。我的示例很差,而你的示例与代码相似。@n另外,为了不污染范围,我不会建议这样做。通过将
for
循环的每个部分放在单独的对齐行上,可以很容易地使其更具可读性。当您有一个结束迭代器时,除了要使用的迭代器之外,还需要在循环之前有一个副本,这也很有用;如果您在for循环初始化步骤中执行此操作,出于常量正确性的原因,这也是一个混合端迭代器和当前迭代器的问题。有时您也有多个迭代器,比如说您正在考虑成对项。有时,您可能会维护无法在for循环中初始化的不同类型的数据,例如,int和float在逻辑上总是相同的值。当然,这也可以写成
inti;对于(i=0;IsStillOk(i);++i){doStuff();}/*现在我们可以将i的最终值用于*/
,那么赋值仍然在
中。谢谢。我看到的代码将它作为第一个方法,但我认为它是为了可读性,因为它是在一个小方法中,并且对最终值没有任何作用。我的示例很差,而你的示例与代码相似。@n另外,为了不污染范围,我不会建议这样做。通过将
for
循环的每个部分放在单独的对齐行上,可以很容易地使其更具可读性。当您有一个结束迭代器时,除了要使用的迭代器之外,还需要在循环之前有一个副本,这也很有用;如果您在for循环初始化步骤中执行此操作,出于常量正确性的原因,这也是一个混合端迭代器和当前迭代器的问题。有时您也有多个迭代器,比如说您正在考虑成对项。有时,您可能会维护无法在for循环中初始化的不同类型的数据,例如,int和float在逻辑上总是相同的值。再加上几个理由。