Сообщение 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
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:
Для любого контейнера это 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
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