给定一个std :: set :: iterator,得到一个指向下一个元素的迭代器

时间:2019-01-29 03:00:05

标签: c++ iterator

如果我有一个std::set::iterator,如何快速生成一个指向集合中 next 元素的迭代器?此一般问题的特定用例如下:

假设我有一个std::set,并且我想打印出集合中所有不同的元素对。我相信我不能写类似my_set.begin() + 1的东西,因为set产生的迭代器不能算术(不同于vector产生的迭代器)。那我该如何实现呢?

我想出的解决方案是

int main(){
    set<int> my_set {1,4,6};
    for (auto it = my_set.begin(); it != my_set.end(); it++) {
        int first_number = *it;
        for (auto it2 = it; it2!= my_set.end(); it2++) {
            if (it2 == it){it2++;} // I don't want the second number to be equal to the first
            if (it2 == my_set.end()) {break;} //If I don't put this in, it will eventually try to access my_set.end(), giving bad behavior. 
            int second_number = *it2;
            cout << "(" << first_number << ", " << second_number << ")" << endl;
        }
    }
    return 0;
}

输出:

(1, 4)
(1, 6)
(4, 6)
Program ended with exit code: 0

但是我认为这很麻烦,必须手动迭代it2,然后检查它是否还没有成为my_set.end()。我该如何做得更好?

我试图使it2循环看起来像

for (auto it2 == it; it2!= my_set.end(); it2++) {...

使其以it2开头,比it大一个,但对此语法不满意。

如果这个问题以前出现过,我们深表歉意。我找不到它。

1 个答案:

答案 0 :(得分:4)

std::next可用于获取一个在一个调用中相对于现有迭代器高级的新迭代器(如果未传递第二个参数,则仅进行一次高级推进),因此您的代码应该可以只是:

#include <iterator>  // For std::next

int main(){
    set<int> my_set {1,4,6};
    for (auto it = my_set.begin(); it != my_set.end(); ++it) {
        int first_number = *it;
        for (auto it2 = std::next(it); it2 != my_set.end(); ++it2) {
            int second_number = *it2;
            cout << "(" << first_number << ", " << second_number << ")" << endl;
        }
    }
    return 0;
}

Try it online!

请注意,我还将您的it++ / it2++表达式更改为++it / ++it2;对于迭代器而言,这对于性能而言可能很重要,因为后缀增量必然会使新的迭代器对象返回,而前缀增量可以更便宜地在适当位置修改迭代器(仅返回对迭代器本身的引用,而无需复制)。