如何在循环中构造带有增量的 std::list 迭代器

发布于 2024-08-22 09:14:56 字数 503 浏览 4 评论 0原文

我正在尝试对 std::list 进行双循环以对每对元素进行操作。但是,我在初始化第二个迭代器时遇到一些问题。我想写的代码是:

for(std::list<int>::iterator i = l.begin(); i != l.end(); ++i) {
    for(std::list<int>::iterator j = i+1; j != l.end(); ++j) {
        ...
    }
}

这不起作用,因为列表迭代器不是随机访问的,所以你不能做+1。但我在寻找一个简洁的替代方案时遇到了一些麻烦;编译器似乎对 std::list::iterator j(i)++; 不太满意,我对此抱有一些希望。实现我想要的似乎我将不得不有一些尴尬的额外增量,这不能很好地适应 for 循环的结构。

有明显的替代方案(例如使用向量!),但在我看来,应该有一些相当简洁的方法来做到这一点,但我目前还没有看到。

预先感谢您的帮助:)

I'm trying to do a double-loop over a std::list to operate on each pair of elements. However, I'm having some trouble initialising the second iterator. The code I'd like to write is:

for(std::list<int>::iterator i = l.begin(); i != l.end(); ++i) {
    for(std::list<int>::iterator j = i+1; j != l.end(); ++j) {
        ...
    }
}

That doesn't work because list iterators aren't random-access, so you can't do +1. But I'm having some trouble finding a neat alternative; the compiler doesn't seem to be very happy with std::list<int>::iterator j(i)++; which I had some hope for. Achieving what I want seems like I'm going to have to have some awkward extra increment which won't fit the structure of the for loop nicely.

There are obvious alternatives (using a vector, for example!) but it seems to me that there should be some reasonably neat way of doing this which I'm just not seeing at the moment.

Thanks in advance for any help :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

作妖 2024-08-29 09:14:56
for(std::list<int>::iterator i = l.begin(); i != l.end(); ++i) {
    std::list<int>::iterator j = i;
    for(std::advance(j, 1); j != l.end(); ++j) {
        ...
    }
}
for(std::list<int>::iterator i = l.begin(); i != l.end(); ++i) {
    std::list<int>::iterator j = i;
    for(std::advance(j, 1); j != l.end(); ++j) {
        ...
    }
}
挽清梦 2024-08-29 09:14:56

怎么样:

for (std::list<int>::iterator i = l.begin(); i != l.end(); ++i) {
    for (std::list<int>::iterator j = i; ++j != l.end(); ) {
        // ...
    }
}

How about:

for (std::list<int>::iterator i = l.begin(); i != l.end(); ++i) {
    for (std::list<int>::iterator j = i; ++j != l.end(); ) {
        // ...
    }
}
妳是的陽光 2024-08-29 09:14:56
for(std::list<int>::iterator i = l.begin(); i != l.end(); ++i) {
    std::list<int>::iterator j = i; ++j;
    for(; j != l.end(); ++j) {
        ...
    }
}

回到游戏中!

实际上,这是数值算法中非常常见的习惯用法,所以我不认为它丑陋。

for(std::list<int>::iterator i = l.begin(); i != l.end(); ++i) {
    std::list<int>::iterator j = i; ++j;
    for(; j != l.end(); ++j) {
        ...
    }
}

Back in the game!

Actually, this a pretty common idiom in numerical algorithms, so I do not see it as ugly.

烂柯人 2024-08-29 09:14:56

我只是放弃了我在德克金特利的回答中的想法:

template <typename Iter, typename Dist>
Iter advance_copy(Iter pIter, const Dist& pOffset)
{
    std::advance(pIter, pOffset);

    return pIter;
}

// ...

typedef std::list<int> int_list;

for(int_list::iterator i = l.begin(); i != l.end(); ++i)
{
    for(int_list::iterator j = advance_copy(i, 1); j != l.end(); ++j)
    {
    }
}

你也可以制作另一类实用函数,以帮助使其简洁:

// for consistency,
template <typename Iter>
void increment(Iter& pIter)
{
    ++pIter;
}

template <typename Iter>
Iter increment_copy(Iter pIter)
{
    return ++pIter;
}

// ...

typedef std::list<int> int_list;

for(int_list::iterator i = l.begin(); i != l.end(); ++i)
{
    for(int_list::iterator j = increment_copy(i); j != l.end(); ++j)
    {
    }
}

I'm just going off the idea I had in dirkgently's answer:

template <typename Iter, typename Dist>
Iter advance_copy(Iter pIter, const Dist& pOffset)
{
    std::advance(pIter, pOffset);

    return pIter;
}

// ...

typedef std::list<int> int_list;

for(int_list::iterator i = l.begin(); i != l.end(); ++i)
{
    for(int_list::iterator j = advance_copy(i, 1); j != l.end(); ++j)
    {
    }
}

You can make another class of utility functions too, to help make it concise:

// for consistency,
template <typename Iter>
void increment(Iter& pIter)
{
    ++pIter;
}

template <typename Iter>
Iter increment_copy(Iter pIter)
{
    return ++pIter;
}

// ...

typedef std::list<int> int_list;

for(int_list::iterator i = l.begin(); i != l.end(); ++i)
{
    for(int_list::iterator j = increment_copy(i); j != l.end(); ++j)
    {
    }
}
九局 2024-08-29 09:14:56

简单的“简洁”替代方案可以基于以下事实:列表迭代器是具有重载运算符的用户定义类型的对象(而不是内置类型)。 (当然,这并没有正式保证,但是根据列表容器的性质,人们可以预期这一点。)因此,可以将重载的前缀 ++ 运算符应用于临时列表迭代器类型的对象。

要实现您想要的效果,您只需创建 i 的临时副本,使用前缀 ++ 递增它,然后使用结果值初始化 j< /code>

for(std::list<int>::iterator i = l.begin(); i != l.end(); ++i) { 
  for(std::list<int>::iterator j = ++std::list<int>::iterator(i); j != l.end(); ++j) { 
    ... 
  } 
} 

就是这样。请注意,这个技巧相当流行,并且在实际代码中有时会遇到。另请注意,它通常不适用于 std::vector,因为许多实现使用普通内置指针作为向量迭代器,但它通常可以与 std::list 一起使用>。

然而,就我个人而言,我不会在我的代码中真正使用它。您已经收到了几个很好的答案,它们通过添加额外的代码行来实现此目的。

The straightforward "neat" alternative can be based on the fact that list iterator is an object of user-defined type with overloaded operators (as opposed to a built-in type). (Of course, this is not formally guaranteed, but one can expect this based on the nature of the list container.) For this reason, it is possible to apply the overloaded prefix ++ operator to a temporary object of list iterator type.

To achieve what you want you just need to create a temporary copy of i, increment it using the prefix ++ and then use the resultant value to initialize j

for(std::list<int>::iterator i = l.begin(); i != l.end(); ++i) { 
  for(std::list<int>::iterator j = ++std::list<int>::iterator(i); j != l.end(); ++j) { 
    ... 
  } 
} 

And that's it. Note, that this trick is fairly popular and can be encountered in real code from time to time. Note also, that it will not generally work with std::vector because many implementations use ordinary built-in pointers as vector iterators, but it will normally work with std::list.

However, personally, I wouldn't really use this in my code. You have already received several good answers that do this by adding an extra line of code.

她说她爱他 2024-08-29 09:14:56

我会采纳肖恩的建议,除了让它成为一个 while 循环:

for (std::list<int>::iterator i = l.begin(); i != l.end(); ++i) {
    std::list<int>::iterator j( i ); 
    while( ++j != l.end() ) {
        // ...
    }
}

I'd go for Sean's suggestion, except make it a while loop:

for (std::list<int>::iterator i = l.begin(); i != l.end(); ++i) {
    std::list<int>::iterator j( i ); 
    while( ++j != l.end() ) {
        // ...
    }
}
失去的东西太少 2024-08-29 09:14:56

如果您已经在使用 Boost,那么最简单的方法是使用 boost::next

for(std::list<int>::iterator i = l.begin(); i != l.end(); ++i)
    for(std::list<int>::iterator j = boost::next(i); j != l.end(); ++j)

If you're already using Boost, then the easiest approach is to use boost::next.

for(std::list<int>::iterator i = l.begin(); i != l.end(); ++i)
    for(std::list<int>::iterator j = boost::next(i); j != l.end(); ++j)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文