C++ 我应该重写循环头来迭代STL向量吗?
哪个更好C++ 我应该重写循环头来迭代STL向量吗?,c++,stl,vector,C++,Stl,Vector,哪个更好 for (auto anItem = aVector.begin(), endVector = aVector.end(); anItem != endVector ; ++anItem ) 或 我总是使用第二种方法——简单的方法 我相信您期望第一个更快,但std::vector::end()的典型实现是返回指向向量中最后一个元素之后的第一个元素的简单指针,因此在第二种情况下实际上没有性能改进,因为end()始终是内联函数。当您在常量迭代器中存储current end()时,可能会
for (auto anItem = aVector.begin(), endVector = aVector.end(); anItem != endVector ; ++anItem )
或
我总是使用第二种方法——简单的方法 我相信您期望第一个更快,但std::vector::end()的典型实现是返回指向向量中最后一个元素之后的第一个元素的简单指针,因此在第二种情况下实际上没有性能改进,因为end()始终是内联函数。当您在
常量迭代器中存储current end()时,可能会有性能改进,如下所示:
const decltype(aVector.end()) endVector = aVector.end();
for (auto anItem = aVector.begin(); anItem != endVector ; ++anItem )
int test1(std::vector<int>& a)
{
int retVal = 0;
for (std::vector<int>::iterator it = a.begin(), aend = a.end(); it != aend; ++it)
{
retVal += *it;
}
return retVal;
}
int test2(std::vector<int>& a)
{
int retVal = 0;
for (std::vector<int>::iterator it = a.begin(); it != a.end(); ++it)
{
retVal += *it;
}
return retVal;
}
但是这个循环和第一个循环在很多情况下都不如第二个循环安全。这就是为什么我几乎总是看到第二个循环
[更新]
在谈到性能时,我不认为第一个循环比第二个循环有任何优势。现代编译器可以检测到aVector.end()结果在整个循环中没有变化,因此可以自由地进行优化。第一个循环的唯一性能优势可能是当aVector在循环中发生变化时,但这会导致错误的行为
所以,无论从哪个角度来看这个问题,第二个循环总是更好的
[更新2]
只是检查一下。我编写了两个类似这样的函数:
const decltype(aVector.end()) endVector = aVector.end();
for (auto anItem = aVector.begin(); anItem != endVector ; ++anItem )
int test1(std::vector<int>& a)
{
int retVal = 0;
for (std::vector<int>::iterator it = a.begin(), aend = a.end(); it != aend; ++it)
{
retVal += *it;
}
return retVal;
}
int test2(std::vector<int>& a)
{
int retVal = 0;
for (std::vector<int>::iterator it = a.begin(); it != a.end(); ++it)
{
retVal += *it;
}
return retVal;
}
inttest1(std::vector&a)
{
int-retVal=0;
对于(std::vector::iterator it=a.begin(),aend=a.end();it!=aend;++it)
{
retVal+=*它;
}
返回返回;
}
int test2(std::vector&a)
{
int-retVal=0;
对于(std::vector::iterator it=a.begin();it!=a.end();++it)
{
retVal+=*它;
}
返回返回;
}
并编译成汇编程序g++-O3-S
。我的计算机/编译器上的汇编程序代码没有差别——但这并不意味着它们在所有情况下都没有差别。第二种更好,因为所有的程序员都使用它(是的,100%)。(假设在迭代过程中没有删除任何内容,在这种情况下,for
循环不是最佳选择)实际编译的循环?(另外,您是否考虑过(auto&&anItemNotAnIteratorLikeInYourExamples:aVector)
?)的)它们不一定相同,这取决于循环体。@PiotrNycz我不确定。许多会导致第一个失败的操作也会使向量中的迭代器无效。@JamesKanze Safer并不意味着100%安全:D将大小重新调整为较小的大小并擦除元素通常不会使向量迭代器无效-但第一个循环将尝试在current end()上迭代。,,第二种形式在这方面也不安全。我确实测量过这一点(一段时间以前),而第一种形式(在最初的帖子中)的速度要快得多。对于几乎不起任何作用的循环;在大多数情况下,我同意差异可以忽略不计,并且您应该使用编码指南指定的形式(这反过来应该基于可读性,这是旁观者的看法)。@JamesKanze只是为了确定:您对没有改变向量大小的循环进行了全面优化测试(如g++-O3)?我相信,对于完全优化和不改变向量大小的循环,性能不会改变——但我没有测量……我的测试也使用了-O3
。它们已经相当老了,编译器可能已经变得更好了,但是有一个可测量的差异。(并不是说我会因为它而改变我的风格。)@JamesKanze我一分钟前刚刚在某台服务器计算机(sparc SUNW,Sun-Fire-480R)上用一些非常旧的编译器(g++4.1.1)运行了一个测试,使用g++-O3-S
为两个函数生成汇编程序输出,使用这两种方法求和所有vector
元素。这些风格之间的汇编代码没有区别。直到最近我才感觉到这一点。然而,在我目前工作的地方,第一种形式更为常见,并且是编码指南所要求的。(如果您还需要访问循环中的end
,则最好使用第一种形式。这种情况通常不存在,但也可能发生。)