Имея std :: set :: iterator, получить итератор, указывающий на следующий элемент - PullRequest
0 голосов
/ 29 января 2019

Если у меня есть std::set::iterator, как быстро создать итератор, который указывает на элемент следующий в наборе?Ниже приведен конкретный вариант использования этого общего вопроса:

Предположим, у меня есть 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 голосов
/ 29 января 2019

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;
}

Попробуйте онлайн!

Обратите внимание, что я также изменил ваши it++ / it2++ выражения на ++it /++it2;для итераторов это может быть важно для производительности, поскольку постфиксное приращение обязательно заставляет возвращаться новые объекты итератора, в то время как префиксное приращение может модифицировать итератор на месте намного дешевле (возвращая только ссылку на сам итератор, копий не требуется).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...