C++ 向后迭代容器 N 步

C++ iterate container backwards N steps

在 C++ 中,我可以使用 reverse_iterator 向后循环容器元素,例如 list

如何遍历一定数量的元素?没有到达起点?此代码有效,但我觉得有更好的方法。

std::list<int> mylist{1,2,3,4,5};
int cnt = 3;
for (auto rit = mylist.rbegin(); rit != mylist.rend(); ++rit) {
    if (cnt == 0) break;
    std::cout << *rit << " ";
    --cnt;
}

预期输出 {5, 4, 3}

您可以按如下方式调整循环:

for (auto rit = mylist.rbegin(); rit != std::next(mylist.rbegin(), 3); ++rit)
{
   std::cout << *rit << " ";
}

但请注意,为了使其可靠地工作,您需要检查列表的大小是否至少为 3 或将参数调整为 std::next,如 const auto n = std::min<std::size_t>(3, mylist.size());.

使用 C++20,您应该可以使用(显然未测试)

#include <ranges>

for (int n : mylist | std::ranges::reverse_view | std::ranges::take_view(3))
  std::cout << n << "\n";

这使得大小测试变得多余,因为 take_view 受范围大小的限制(它在内部执行此检查)。

我不会将 incrementing/decrementing 和检查条件放在循环体中,而是将其放在您最期望的位置:

std::list<int> mylist{1,2,3,4,5};
int cnt = 3;
for (auto rit = mylist.rbegin(); rit != mylist.rend() && cnt > 0; ++rit,--cnt) {
    std::cout << *rit << " ";
}

例如,现在您可以在循环体的任何位置添加一个 continue 而不会破坏循环。

PS:实际上我更喜欢其他答案,但我会留下这个,因为它的变化很小,恕我直言,如果可能的话,应该避免在循环体内递增/检查循环计数器(这里是可能的)。

Not reaching the beginning?

如果你能保证,那么

std::copy_n(mylist.rbegin(), 3, std::ostream_iterator<int>(std::cout, " "));

或者更安全

std::copy_n(mylist.rbegin(), std::min(mylist.size(), std::list<int>::size_type(3)), std::ostream_iterator<int>(std::cout, " "));

LIVE