如何使用increment在循环中构造一个std :: list迭代器

时间:2010-02-15 22:59:52

标签: c++ stl iterator

我正在尝试对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<int>::iterator j(i)++;并不满意。实现我想要的东西似乎我将不得不有一些尴尬的额外增量,它不能很好地适应for循环的结构。

有明显的替代方案(例如使用矢量!)但在我看来应该有一些合理利落的方式来做这件事,我现在还没有看到。

提前感谢您的任何帮助:)

7 个答案:

答案 0 :(得分:9)

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) {
        ...
    }
}

答案 1 :(得分:8)

怎么样:

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

答案 2 :(得分:4)

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

回到游戏中!

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

答案 3 :(得分:2)

我只是简单地回答了我的想法:

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)
    {
    }
}

答案 4 :(得分:2)

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

要实现您的目标,您只需创建i的临时副本,使用前缀++递增它,然后使用结果值初始化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) { 
    ... 
  } 
} 

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

但是,就个人而言,我不会在我的代码中使用它。通过添加额外的代码行,您已经收到了几个很好的答案。

答案 5 :(得分:1)

我会选择Sean的建议,除了让它成为一个循环:

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

答案 6 :(得分:0)

如果您已经在使用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)