LINUX.ORG.RU

Валидность указателя, возвращаемого итератором

 ,


0

2

ВНИМАНИЕ: Это вопрос не о валидности самого итератора!

Привет Лор,

Функция итератора operator->() возвращает указатель. Будет ли валидным этот указатель после каких-то неконстантных действий с итератором? Ну, то есть, если итератор при разыменовывании просто возвращает указатель непосредственно на сам элемент контейнера, то всё понятно. А может ли он делать какие-то другие хитрые действия и возвращать указатель на какой-нибудь временный объект?

Вот 2 примера, которые показывают, что всё вроде бы работает (по крайней мере, с std::vector). Но можно ли на это полагаться с произвольным итератором, не является ли это UB? Более важно, если я делаю свой итератор, обязан ли я обеспечивать подобную работу?

#include <iostream>
#include <vector>

int main(void)
{
    std::vector<int> x;

    x.push_back(1); //first element
    x.push_back(2); //second element

    std::vector<int>::iterator i(x.begin()); // declare an iterator pointing to the first element (0)

    int * xptr=i.operator->(); // dereference the iterator and save the pointer

    ++i; // increment the iterator

    std::cout<<*xptr<<'\n'; // get dereferenced value

    return 0;
}
#include <iostream>
#include <vector>

int main(void)
{
    std::vector<int> x;

    x.push_back(1); //first element
    x.push_back(2); //second element

    std::vector<int>::iterator *iptr=new std::vector<int>::iterator(x.begin()); // declare an iterator pointing to the first element (0)

    int * xptr=iptr->operator->(); // dereference the iterator and save the pointer

    delete iptr; //delete the iterator

    std::cout<<*xptr<<'\n'; // get dereferenced value

    return 0;
}

Ответ на: комментарий от tailgunner

Кто-то из нас читает невнимательно)

По ссылке валидность итератора при неконстантных действиях с контейнером. А у меня вопрос о валидности указателя при неконстантных действиях с итертором, а с контейнером не делается вообще ничего!

Pythagoras ★★ ()
Ответ на: комментарий от Pythagoras

Если вопрос звучит точно так, как задан в хедпосте, я даже не знаю, как ответить - там, наверное, какой-то подвох.

tailgunner ★★★★★ ()

В описании контейнера оговаривается в каких случаях итератор остается валидным, а в каких инвалидируется.

andreyu ★★★★★ ()

вообще возвращается указатель на объект. в этом и есть смысл итератора — доступ к объекту. Но в vector<bool>, например, это будет прокси-объект, то есть вернуть не указатель на реальный объект никто не мешает, но не комильфо считается. так что лучше доку по контейнеру почитать.

ossa ★★ ()

сли я делаю свой итератор, обязан ли я обеспечивать подобную работу?

Кому обязан? Свой итератор вообще может быть чисто вирутальным и делать что тебе вздумается. Если хочешь использовать его в каких-то стандартных алгоритмах, то нужно смотреть какой тип итератора требуется и каким минимумом свойств он должен обладать.

mashina ★★★★★ ()
Ответ на: комментарий от ossa

Но в vector<bool>, например, это будет прокси-объект

Хм, поменял в своём примере на std::vector<bool>, получил сообщение от компилятора, что operator->() не определён. Почему так получилось?

Потом поменял на std::map<int, bool>, и всё опять заработало. Как это интерпретировать?

И что значит «не комильфо»? UB?

Pythagoras ★★ ()

но можно ли на это полагаться с произвольным итератором

Нет. Смотри std::vector<bool>, ЕМНИП.

KblCb ★★★★★ ()
Ответ на: комментарий от Pythagoras

Это происходит потому что std::vector<bool>, ЕМНИП, битовое поле. И итератор всегда возвращает временный bool.

KblCb ★★★★★ ()
Ответ на: комментарий от mashina

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

Can be dereferenced as an rvalue

Правильно ли я понимаю, что пытаясь сохранять указатель, как в примрах выше, я его разыменовываю как lvalue? Или нет?

Pythagoras ★★ ()

Функция итератора operator->() возвращает указатель.

Я не очень большой специалист по C++, но по-моему, функция Iterator::operator->() должна возвращать тип Iterator::pointer, который не обязан быть голым указателем.

Почему нельзя использовать сам итератор вместо указателя?

Если нельзя, попробуй сделать &(*iptr), но не знаю, может ли это вызвать UB и при каких условиях.

proud_anon ★★★★★ ()
Последнее исправление: proud_anon (всего исправлений: 3)
Ответ на: комментарий от Pythagoras

Правильно ли я понимаю, что пытаясь сохранять указатель, как в примрах выше, я его разыменовываю как lvalue? Или нет?

Почти так, правильнее было бы сохранять его как &*iptr.

mashina ★★★★★ ()

Если контейнер не меняется, с чего вдруг сохраненный указатель должен указатель на элемент контейнера становиться невалидным?

invy ★★★★★ ()
Ответ на: комментарий от invy

Если контейнер не меняется, с чего вдруг сохраненный указатель должен указатель на элемент контейнера становиться невалидным?

Потому что это может быть указатель не на элемент контейнера.

Pythagoras ★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.