我正在尝试对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循环的结构。
有明显的替代方案(例如使用矢量!)但在我看来应该有一些合理利落的方式来做这件事,我现在还没有看到。
提前感谢您的任何帮助:)
答案 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)