3

我经常在旧代码中看到

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% 重复另一个问题,请告诉我并关闭此问题。没问题。

4

2 回答 2

1

C++(在本例中为 C++11)标准似乎并没有为此留下太多空间。它明确6.5.3 The for statement /1指出(我的重点):

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

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

需要符合要求的实现来模拟(仅)抽象机器的可观察行为,如下所述。

该规定有时被称为“好像”规则,因为只要从可观察的行为中可以确定,结果就好像该要求已被遵守,实施可以自由地忽略本国际标准的任何要求的程序。

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

实现是否可以确定这取决于很多事情,并且随着标准的每次新迭代,这些事情似乎都会扩大。我正在考虑的事情是波动性,来自多个线程的访问constexpr等等。

您可能必须非常努力地通知编译器可以免费执行此操作(即使那样,也不需要这样做)。

我可以看到您拥有的第一个代码示例的唯一问题是它num可能存在的时间超过了必要的时间(如果它存在的原因只是为了管理这个循环)。但是,这可以通过显式限制范围来轻松解决,例如使用“small-change”:

{
    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.
于 2018-06-22T00:39:36.243 回答
0

The exact answer to my question is to use

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

}

because

  • it prevent calls to GetNum() on each cycle
  • variable num is not exposed outside of the loop

Credits go to user Nawaz!

I also used ++i instead of i++. Reason: https://www.quora.com/Why-doesnt-it-matter-if-we-use-I++-or-++I-for-a-for-loop

于 2018-08-31T09:38:00.587 回答