Информация об изменениях

Сообщение Re: получить указатель из итератора от 06.12.2022 18:36

Изменено 06.12.2022 19:49 watchmaker

Re: получить указатель из итератора
Здравствуйте, B0FEE664, Вы писали:

BFE>Есть некий итератор стандартного контейнера, а из него надо получить указатель на объект этого контейнера.

BFE>Многие советуют использовать конструкцию вида:
BFE>ptr = &*it;

Вообще-то, std::addressof(*it). Так как operator& не обязан возвращать указатель, а даже если и возвращает, то не обязан возвращать его для элемента *it.

BFE>но для past-the-end итератора такая конструкция не валидна.


Верно.


BFE>Вроде бы для past-the-end итератора можно использовать конструкцию вида:

BFE>ptr = it.operator->();
Нельзя

BFE>Есть ли гарантия, что it.operator->() вернёт именно указатель, а не некий тип его имитирующий?


Нет.
В C++ специально сделали для opeator-> особые правила, для этого случая.


Для любого контейнера это UB.

Вообще, если собираешься с ассертами, то оно просто в библиотеке упадёт и всё
https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/debug/safe_iterator.h#L314-L322
https://github.com/llvm-mirror/libcxx/blob/master/include/list#L367-L368
Ну или на аналогичной строке в твоей версии STL
Re: получить указатель из итератора
Здравствуйте, B0FEE664, Вы писали:

BFE>Есть некий итератор стандартного контейнера, а из него надо получить указатель на объект этого контейнера.

BFE>Многие советуют использовать конструкцию вида:
BFE>ptr = &*it;

Вообще-то, std::addressof(*it). Так как operator& не обязан возвращать указатель, а даже если и возвращает, то не обязан возвращать его для элемента *it.

Только даже это не всегда имеет смысл: попробуй в пресловутом std::vector<bool> адрес элемента взять.

BFE>но для past-the-end итератора такая конструкция не валидна.


Верно.


BFE>Вроде бы для past-the-end итератора можно использовать конструкцию вида:

BFE>ptr = it.operator->();
Нельзя

BFE>Есть ли гарантия, что it.operator->() вернёт именно указатель, а не некий тип его имитирующий?

Нет.
В C++ специально сделали для opeator-> особые правила, для этого случая, чтобы можно было возвращать не указатели из opeator->, а компилятор потом их сам в цепочку вызовов выстраивал.

BFE>Верно ли, что для пустого контейнера x, следующий код — это UB:

BFE>bool bEmpty = std::begin(x).operator->() == std::end(x).operator->()

Для любого контейнера это UB.
Даже для std::basic_string формально не разрешено, хотя при этом str[str.size()] содержит нулевой символ, который можно читать.


Вообще, если собираешься с ассертами, то оно просто в библиотеке упадёт и всё
https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/debug/safe_iterator.h#L314-L322
https://github.com/llvm-mirror/libcxx/blob/master/include/list#L367-L368
Ну или на аналогичной строке в твоей версии STL