for循环中的上限需要保存在额外的变量中吗?

时间:2017-10-26 17:05:49

标签: c++ c++11 for-loop upperbound

我经常在旧代码中看到

DWORD num = someOldListImplementation.GetNum();
for (DWORD i = 0; i < num; i++)
{
    someOldListImplementation.Get(i);
}

而不是

   for (DWORD i = 0; i < someOldListImplementation.GetNum(); i++)
   {
        someOldListImplementation.Get(i);
   }

我想第一个实现应该阻止在每个周期调用GetNum()。但是,是否存在C ++ 11中的编译器对第二个代码片段进行一些优化的情况,这使得num变量过时了?

我是否应该总是更喜欢第一次实施?

如果该问题重复100%的另一个问题,请告诉我并关闭此问题。没问题。

2 个答案:

答案 0 :(得分:1)

C ++(在这种情况下为C ++ 11)标准不会似乎留有很大的空间。它在6.5.3 The for statement /1中明确指出(我的重点):

  

条件指定一个测试, 在每次迭代之前进行 ,以便在条件变为假时退出循环;

但是,如1.9 Program execution /1中所述:

  

需要遵循一致的实现来(仅)模拟抽象机的可观察行为,如下所述。

     

该规定有时称为“假设”规则,因为实施可以自由地忽略本国际标准的任何要求,只要其结果表明该要求已得到遵守,可以根据程序的可观察行为确定。

因此,如果实现可以确定GetNum()的返回值在循环期间不会改变,则它可以自由地优化除第一个调用之外的所有调用。

是否可以确定实现 取决于很多事情,并且该数目似乎随着标准的每次新迭代而扩展。我想到的是波动性,从多个线程进行的访问,constexpr等。

您可能需要相当费力地[em> 来通知编译器可以自由执行此操作(即使这样,也不需要 这样做)。

在您拥有的第一个代码示例中,我唯一看到的问题是num的存在时间可能超过必需的时间(如果存在的原因仅是为了管理此循环)。但是,可以通过明确限制范围来轻松解决此问题,例如使用“小更改”:

{
    DWORD num = someOldListImplementation.GetNum();
    for (DWORD i = 0; i < num; i++)
    {
        someOldListImplementation.Get(i);
    }
}
// That num is no longer in existence.

或通过将其合并到for语句本身中:

for (DWORD num = someOldListImplementation.GetNum(), i = 0; i < num; ++i)
{
    someOldListImplementation.Get(i);
}
// That num is no longer in existence.

答案 1 :(得分:0)

我的问题的确切答案是使用

for (auto i = 0, num = x.GetNum(); i < num; ++i) 
{ 

}

因为

  • 它可以防止在每个周期调用GetNum()
  • 变量num没有暴露在循环之外

信用归用户Nawaz!

我也用++ i代替了i ++。原因:https://www.quora.com/Why-doesnt-it-matter-if-we-use-I++-or-++I-for-a-for-loop