Проверка, допустим ли итератор

Там какой-либо путь состоит в том, чтобы проверить, является ли итератор (ли это от вектора, списка, двухсторонняя очередь...) (все еще) dereferencable, т.е. не делался недействительным?

Я использовал try-catch, но есть ли более прямой способ сделать это?

Пример: (который не работает),

list<int> l;
for (i = 1; i<10; i++) {
    l.push_back(i * 10);
}

itd = l.begin();
itd++;
if (something) {
    l.erase(itd);
}

/* now, in other place.. check if itd points to somewhere meaningful */
if (itd != l.end())
{
    //  blablabla
}
63
задан Peter Wood 22 January 2013 в 08:33
поделиться

9 ответов

Я предполагаю, что вы имеете в виду «является действительным итератором», что оно не было недействительным из-за изменений в контейнер (например, вставка / стирание в / из вектора). В этом случае нет, вы не можете определить, является ли iTerator (безопасно) разыскиваемым.

60
ответ дан 24 November 2019 в 16:21
поделиться
if (iterator != container.end()) {
   iterator is dereferencable !
}

Если итератор не равен container.end () и не может быть потерян, вы делаете что-то неправильно.

-121--944871-

В настоящее время в методе Work имеется Thread.Sleep (0) , где отсутствуют предметы очереди. Измените его на что-либо больше 0, и использование ЦП прекратится. Попробуйте 10 , чтобы начать с...

-121--4817915-

Попытки и ловля небезопасны, вы не будете, или, по крайней мере, редко бросаете, если итератор «вне границ».

что алемьерус сказать, итератор всегда может быть обособлен. Неважно, какая уродливость лежит под ним. Вполне возможно выполнить итерацию в другие области памяти и запись в другие области, которые могут содержать другие объекты. Я смотрел на код, смотрел, как переменные меняются без особой причины. Это ошибка, которую очень трудно обнаружить.

Также целесообразно помнить, что вставка и удаление элементов может потенциально привести к недействительности всех ссылок, указателей и итераторов.

Мой лучший совет состоит в том, чтобы держать вас итераторами под контролем и всегда держать под рукой «конечный» итератор, чтобы иметь возможность проверить, находитесь ли вы в «конце строки», так сказать.

3
ответ дан 24 November 2019 в 16:21
поделиться

Обычно вы проверяете его, проверяя, отличается от того, отличается от конца (), как

if (it != container.end())
{
   // then dereference
}

, кроме того, используя обработку исключения для замены логики, плохой с точки зрения проектирования и производительности. Ваш вопрос очень хороший, и он окончательно стоит замены в вашем коде. Обработка исключений, как и имена, как называются только для редких неожиданных проблем.

9
ответ дан 24 November 2019 в 16:21
поделиться

Просмотрите стандартные tallibs для JSP-страниц, в частности < c: url > тэги.

http://onjava.com/pub/a/pub/a/onjava/2002/05/08/jstl.html?page=2

Я считаю, что он также обрабатывает атрибут jsession-id, если файлы cookie недоступны.

-121--3796825-

Еще одна недавняя статья, предоставляющая реальный жизненный опыт по этой теме, - « Зрелый скрум на систематическом », соавтор Карстен Русенг Якобсен, Джефф Сазерленд

-121--2306833-

Непортативный ответ: Да - в итераторах STL Visual Studio

есть режим «отладки», который делает именно это. Вы бы не хотели включать это в корабельных построениях (есть накладные расходы), но полезно в проверенных построениях.

Читайте об этом на VC10 здесь (эта система может и фактически изменяет каждую версию, поэтому найдите документы, относящиеся к вашей версии).

Изменить Также следует добавить: отладочные итераторы в visual studio предназначены для немедленного расчленения при их использовании (вместо неопределенного поведения); не позволять «запрашивать» их состояние.

10
ответ дан 24 November 2019 в 16:21
поделиться

Есть ли способ проверить, является ли итератор (будь то из вектора, список, утк ...) (все еще) разграничен, то есть не был недействительным?

Нет, нет. Вместо этого вам необходимо контролировать доступ к контейнеру, в то время как ваш итератор существует, например:

  • Ваша поток не должен изменять контейнер (недействительный итератор), когда он все еще использует экземпляр итератор для этого контейнера

  • , если есть риск То, что другие потоки могут изменить контейнер, пока ваша нить итерация, а затем, чтобы сделать этот сценарий, безопасный поток, ваша нить должна приобретать какую-то блокировку на контейнере (так, чтобы оно предотвращает изменение контейнера, пока он использует итератор )

Работы, такие как ловить исключение, не будут работать.

Это определенный экземпляр более общей проблемы, «могу ли я проверить / обнаруживать, действителен ли указатель?», Ответ на который обычно «нет, вы не можете проверить для него: вместо этого вам нужно управлять Все распределения памяти и удаления в целях знают .

7
ответ дан 24 November 2019 в 16:21
поделиться

Как сказал JDehaan, если итератор не был признан недействительным и указывает в контейнер, вы можете проверить, сравнивая его с помощью Container.end () .

Обратите внимание, что если итератор единственное число - потому что он не был инициализирован или он стал недействительным после того, как мутационная операция на контейнере (итераторы вектора недействительны при увеличении емкости вектора, Например) - единственная операция, которую вам разрешено выступать на ней, является назначением. Другими словами, вы не можете проверить, является ли итератор единственным или нет.

std::vector<int>::iterator iter = vec.begin();
vec.resize(vec.capacity() + 1);
// iter is now singular, you may only perform assignment on it,
// there is no way in general to determine whether it is singular or not
25
ответ дан 24 November 2019 в 16:21
поделиться
if (iterator != container.end()) {
   iterator is dereferencable !
}

Если ваш итератор не равен container.end(), и не является разыскиваемым, вы делаете что-то не так.

-3
ответ дан 24 November 2019 в 16:21
поделиться

Используйте стирание с увеличением:

   if (something) l.erase(itd++);

, так что вы может проверить действительность итератора.

-1
ответ дан 24 November 2019 в 16:21
поделиться

В некоторых контейнерах STL текущий итератор становится недействительным, когда вы стираете текущее значение итератора. Это происходит потому, что операция стирания изменяет внутреннюю структуру памяти контейнера и оператор инкремента на существующем итераторе указывает на неопределенное место.

Когда вы делаете следующее, итератор инкрементируется перед передачей в функцию стирания.

if (something) l.erase(itd++);

1
ответ дан 24 November 2019 в 16:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: