我需要迭代从结尾到beginnig的向量。 “正确”的方式是
for(std::vector<SomeT>::reverse_iterator rit = v.rbegin(); rit != v.rend(); ++rit)
{
//do Something
}
当doSomething涉及了解实际索引时,需要使用rit进行一些计算才能获得它,例如index = v.size() - 1 - (rit - v.rbegin)
如果仍然需要索引,那么我坚信最好使用该索引进行迭代
for(int i = v.size() - 1; i >= 0; --i)
{
//do something with v[i] and i;
}
这会发出警告,i
已签名且v.size()
未签名。
改为
for(unsigned i = v.size() - 1; i >= 0; --i)
在功能上是错误的,因为这实际上是一个无限循环:)
做我想做的事情的美学方法是什么
我希望我不是在寻找不存在的东西:)
答案 0 :(得分:54)
正如您所指出的那样,i >= 0
条件无条件时的问题是条件始终为真。在初始化i
然后在每次迭代后再次减去1时,在检查循环条件后减去1:
for (unsigned i = v.size(); i-- > 0; )
我喜欢这种风格有几个原因:
i
将在循环结束时回绕到UINT_MAX
,但它不会依赖这个行为 - 如果类型是签。依靠无符号的环绕感觉对我来说有点像黑客。size()
一次。>=
。每当我在for
循环中看到该运算符时,我必须重新读取它以确保没有一个错误。答案 1 :(得分:15)
除了多个其他答案中所述的索引之外,没有什么能阻止你的reverse_iterator
循环。这样,您可以在// do the work
部分中根据需要使用迭代器或索引,以获得最低的额外成本。
size_t index = v.size() - 1;
for(std::vector<SomeT>::reverse_iterator rit = v.rbegin();
rit != v.rend(); ++rit, --index)
{
// do the work
}
虽然我很想知道你需要什么索引。访问v[index]
与访问*rit
相同。
答案 2 :(得分:5)
美观赏心悦目! ;)
for(unsigned i = v.size() - 1; v.size() > i; --i)
答案 3 :(得分:2)
我更喜欢反向迭代器变体,因为它仍然易于解释并允许避免与索引相关的错误。
有时您只需使用BOOST_REVERSE_FOREACH
,这会使您的代码看起来如下:
reverse_foreach (int value, vector) {
do_something_with_the_value;
}
实际上,你总是可以对这些类型的循环使用foreach
语句,但它们会变得有点不明显:
size_t i = 0;
foreach (int value, vector) {
do_something;
++i;
}
答案 4 :(得分:0)
尝试做一会儿:
std::vector<Type> v;
// Some code
if(v.size() > 0)
{
unsigned int i = v.size() - 1;
do
{
// Your stuff
}
while(i-- > 0);
}
答案 5 :(得分:0)
嗨我认为更好的方法是在第一个示例中使用迭代器,如果需要获取迭代器索引,可以使用 std :: distance来计算它,如果我理解你的问题
答案 6 :(得分:0)
循环条件i != std::numeric_limits<unsigned>::max()
...或者如果你认为它是详细的,请使用UINT_MAX
。
或其他方式:
for(unsigned j=0, end=v.size(), i=end-1; j<end; --i, ++j)
或
for(unsigned end=v.size(), i=end-1; (end-i)<end; --i)
答案 7 :(得分:-2)
for (it = v.end()-1; it != v.begin()-1; --it)
{
}
"goes to" operator绝对是我头脑中的混乱。
答案 8 :(得分:-3)
我认为:
for(unsigned i = v.size() - 1; i >= 0; --i)
如果你检查,就可以了
!v.empty()
更早的版本。