Здравствуйте, nut888, Вы писали:
N>Какие есть способы проверить был ли итератор инициализирован чем либо или нет N>Также интересует возможность проверки валидности итератора it
You will always get what you always got
If you always do what you always did
Re: Инициализация итераторов
От:
Аноним
Дата:
25.01.08 08:25
Оценка:
Здравствуйте, nut888, Вы писали:
N>Какие есть способы проверить был ли итератор инициализирован чем либо или нет
N>Например
N>
N>/**********************************************/
N>std::vector<int> data;
N>std::vector<int>::iterator it;
N>for(std::vector<int>::iterator i=data.begin(); i!=data.end(); ++i)
N>if(...) it=i;
N>if(???) *it; // Обращение по итератору
N>/*********************************************/
N>
N>Также интересует возможность проверки валидности итератора it
1. Инициализацию нельзя проверить, используйте свой флажок
2. изменение (push_back) вектора вполне себе инвалидирует ваш итератор, и об этом вы тоже не узнаете.
В целом, итератор это такая временная штука, которую лучше использовать так — взял, попользовался, забыл. Долгосрочное хранение итераторов — вешь сложная, это конечно можно делать, но это почти всегда грабли, пожалуй за исключением неизменяемых контейнеров.
Здравствуйте, Аноним, Вы писали:
А>[snipped] А>2. изменение (push_back) вектора вполне себе инвалидирует ваш итератор, и об этом вы тоже не узнаете.
Это такая штука, которая зависит от реализации. В StlPort, например, итераторы в дебажной и релизной (извините за использование сленга) конфигурациях представлены разными типами. Конкретно, итератор вектора в релизной конфигурации — это обычный указатель, а в дебажной — структура, содержащая дополнительную информацию, которая как раз и позволяет диагностировать использование инвалидированных итераторов (при попытке использования инвалидного итератора возбуждается исключение).
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, Left2, Вы писали:
А>>2. изменение (push_back) вектора вполне себе инвалидирует ваш итератор, и об этом вы тоже не узнаете.
L>Насколько я понимаю для вектора это запросто можно узнать сравнив между собой size и capacity. Знатоки стандарта, поправьте если не прав.
Здравствуйте, nut888, Вы писали:
N>Какие есть способы проверить был ли итератор инициализирован чем либо или нет
В данном конкретном случае все, кажется, проще:
/**********************************************/
std::vector<int> data;
std::vector<int>::iterator i;
for (i = data.begin(); i != data.end(); ++i)
if (...)
break;
if (i != data.end())
*it; // Обращение по итератору
Рекомендация по стилю, кстати — в фигурные скобки лучше обрамлять даже один оператор в if/for/...
Ибо написать что-то вроде
if (i != data.end())
LOGLN("accessing the iterator");
*it; // Обращение по итератору
очень легко, а вот отладить потом — не очень...
N>Также интересует возможность проверки валидности итератора it
Хороший STL подскажет assert-ом
It's kind of fun to do the impossible (Walt Disney)
Здравствуйте, Left2, Вы писали:
А>>2. изменение (push_back) вектора вполне себе инвалидирует ваш итератор, и об этом вы тоже не узнаете.
L>Насколько я понимаю для вектора это запросто можно узнать сравнив между собой size и capacity. Знатоки стандарта, поправьте если не прав.
size и capacity чаще всего не равны друг другу и на их сравнении врядли можно сделать какие-то выводы о валидности итераторов. Может быть, ты хотел сказать: сравнив capacity до и после вставки? Ведь инвалидация итераторов вектора происходит в результате реаллокации памяти при изменении рамера памяти, выделенной для элементов вектора. Да, практически, такое решение наверное прокатит — врядли в какой либо реализации STL разработчикам может прийти в голову делать реаллокацию без изменения capacity. Но, если говорить строго, то в стандарте нигде не сказано, что если после вставки элемента capacity не изменилось, то реаллокации не было.
... << RSDN@Home 1.2.0 alpha rev. 787>>
--
Не можешь достичь желаемого — пожелай достигнутого.
L>>Насколько я понимаю для вектора это запросто можно узнать сравнив между собой size и capacity. Знатоки стандарта, поправьте если не прав. R>Может быть, ты хотел сказать: сравнив capacity до и после вставки?
Не совсем так — сравнив size и capacity до вставки. Хотя насчёт сравнения capacity до и после вставки — это идея получше Ведь теоретически имплементация может делать переаллокацию ещё до того, как закончилось capacity, хотя практически трудно себе представить ситуацию когда это было бы оправдано.
R>Ведь инвалидация итераторов вектора происходит в результате реаллокации памяти при изменении рамера памяти, выделенной для элементов вектора. Да, практически, такое решение наверное прокатит — врядли в какой либо реализации STL разработчикам может прийти в голову делать реаллокацию без изменения capacity. Но, если говорить строго, то в стандарте нигде не сказано, что если после вставки элемента capacity не изменилось, то реаллокации не было.
Жаль что стандартом это не оговорено. Но в любом случае спасибо за разьяснения
Здравствуйте, Left2, Вы писали:
L>>>Насколько я понимаю для вектора это запросто можно узнать сравнив между собой size и capacity. Знатоки стандарта, поправьте если не прав. R>>Может быть, ты хотел сказать: сравнив capacity до и после вставки? L>Не совсем так — сравнив size и capacity до вставки...
Теперь понял идею. Наверное тоже должно работать. Но, опять же, слабость обоих приемов в том, что они основаны на предположениях о реализации и не подкреплены стандартом. А кроме того, на практике чаще всего бывает, что в том месте, где происходит вставка, владельцы итераторов не известны, и освежить эти итераторы нет возможности, в этом случае, спасает только переход от вектора к списку.
... << RSDN@Home 1.2.0 alpha rev. 787>>
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, Аноним, Вы писали:
А>>[snipped] А>>2. изменение (push_back) вектора вполне себе инвалидирует ваш итератор, и об этом вы тоже не узнаете.
R>Это такая штука, которая зависит от реализации. В StlPort, например, итераторы в дебажной и релизной (извините за использование сленга) конфигурациях представлены разными типами. Конкретно, итератор вектора в релизной конфигурации — это обычный указатель, а в дебажной — структура, содержащая дополнительную информацию, которая как раз и позволяет диагностировать использование инвалидированных итераторов (при попытке использования инвалидного итератора возбуждается исключение).
Это всё конечно здорово, но использовать это можно лишь при отладке. Если же кому-то придет в голову использовать это в нормальном коде — руки надо отрывать. Потому что, как Вы сказали, "это зависит от реализации".
Здравствуйте, Left2, Вы писали:
L>Не совсем так — сравнив size и capacity до вставки. Хотя насчёт сравнения capacity до и после вставки — это идея получше Ведь теоретически имплементация может делать переаллокацию ещё до того, как закончилось capacity, хотя практически трудно себе представить ситуацию когда это было бы оправдано.
А вдруг, например, vector разделяет тело между несколькими копиями объекта? И при любых модификациях может сделать переаллокацию, соответсвенно?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, Left2, Вы писали:
L>>Не совсем так — сравнив size и capacity до вставки. Хотя насчёт сравнения capacity до и после вставки — это идея получше Ведь теоретически имплементация может делать переаллокацию ещё до того, как закончилось capacity, хотя практически трудно себе представить ситуацию когда это было бы оправдано.
E>А вдруг, например, vector разделяет тело между несколькими копиями объекта? И при любых модификациях может сделать переаллокацию, соответсвенно?
Интересная мысль, но мне кажется, трудно реализуемая. В самом деле, тогда для того, чтобы прошла переаллкокация и инвалидировались итераторы, достаточно не вставки или удаления элемента, а простого изменения значения какого-либо элемента. Такой эффект со стандартом не соглсуется. Ну или нужно прекращать совместное использование содержимого при получении первого же итератора. Но тогда возникает вопрос: а стоит ли игра свеч?
... << RSDN@Home 1.2.0 alpha rev. 787>>
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
R>Интересная мысль, но мне кажется, трудно реализуемая. В самом деле, тогда для того, чтобы прошла переаллкокация и инвалидировались итераторы, достаточно не вставки или удаления элемента, а простого изменения значения какого-либо элемента. Такой эффект со стандартом не соглсуется. Ну или нужно прекращать совместное использование содержимого при получении первого же итератора. Но тогда возникает вопрос: а стоит ли игра свеч?
При получении первого неконстантного.
В целом скорее всего не стоит. Но кто его знает...
Вдруг в какой-нибудь версии будут параноидально экономить память?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>При получении первого неконстантного.
Не получается. Потому, что если мы последовательно получаем два итератора — первый константный, второй — неконстантный, то при получении второго происходит реаллокация и первый становится невалидным (или того хуже — валидным, но ссылающимся на содержимое не того контейнера).
... << RSDN@Home 1.2.0 alpha rev. 787>>
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
R>Не получается. Потому, что если мы последовательно получаем два итератора — первый константный, второй — неконстантный, то при получении второго происходит реаллокация и первый становится невалидным (или того хуже — валидным, но ссылающимся на содержимое не того контейнера).
Да, так не получится.
Зато можно в итераторе хранить указатель на вектор и индекс. Будет медленнее, зато можно не копировать.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском