我经常在旧代码中看到
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%的另一个问题,请告诉我并关闭此问题。没问题。
答案 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