在反向迭代向量

Arm*_*yan 33 c++ iteration stl

我需要迭代从结尾到beginnig的向量."正确"的方式是

for(std::vector<SomeT>::reverse_iterator rit = v.rbegin(); rit != v.rend(); ++rit)
{
    //do Something
}
Run Code Online (Sandbox Code Playgroud)

当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; 
}
Run Code Online (Sandbox Code Playgroud)

这会发出一个i已签名v.size()且未签名的警告.改为

for(unsigned i = v.size() - 1; i >= 0; --i) 在功能上是错误的,因为这实际上是一个无限循环 :)

什么是美学上很好的方式来做我想做的事情

  • 没有警告
  • 不涉及演员阵容
  • 并不过分冗长

我希望我不是在寻找不存在的东西:)

Rob*_*edy 56

正如您所指出的那样,条件是无条件的问题i >= 0是条件始终为真.在初始化时减去1,而不是i在每次迭代后再减1,在检查循环条件后减去1:

for (unsigned i = v.size(); i-- > 0; )
Run Code Online (Sandbox Code Playgroud)

我喜欢这种风格有几个原因:

  • 虽然iUINT_MAX在循环结束时回绕,但它不依赖于该行为 - 如果类型已签名,它将工作相同.依靠无符号的环绕感觉对我来说有点像黑客.
  • 它只调用size()一次.
  • 它不使用>=.每当我在for循环中看到该运算符时,我必须重新读取它以确保没有一个一个错误.
  • 如果更改条件中的间距,则可以使用"转到"运算符.

  • 这不是大小而不是未签名的吗? (3认同)
  • 如果你真的期望有更多的项目而不是"unsigned",@ Yes123,那可能会更好,但正式的正确类型是`std :: vector <SomeT> :: size_type`,或者,现在,只是`auto `. (3认同)

Ste*_*end 16

没有什么能阻止你的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
}
Run Code Online (Sandbox Code Playgroud)

虽然我很想知道你需要什么索引.访问v[index]与访问相同*rit.


Nim*_*Nim 5

在美学上令人愉悦!;)

for(unsigned i = v.size() - 1; v.size() > i; --i)
Run Code Online (Sandbox Code Playgroud)


Pav*_*aka 5

在 C++20 中可以使用范围 ( #include <ranges>)

//DATA
std::vector<int> vecOfInts = { 2,4,6,8 };

//REVERSE VECTOR 
for (int i : vecOfInts | std::views::reverse)
{
     std::cout << i << "  ";
} 
Run Code Online (Sandbox Code Playgroud)

或者如果需要保存在不同的变量中。

//SAVE IN ANOTHER VARIABLE
auto reverseVecOfInts = std::views::reverse(vecOfInts);

//ITERATION
for (int i : reverseVecOfInts)
{
    std::cout << i << "  ";
}
Run Code Online (Sandbox Code Playgroud)