std::string ss("some unknown word"); std::list<char> word(ss.begin(), ss.end()); auto first = word.begin(), last = word.end(), middle = first; size_t p = ss.size()/2; std::advance(middle, p); while (last != first) *(--middle) = *(--last); //результат: own wordnown word 

And why does this cycle behave like the next one?

 // while (p--) // *(--middle) = *(--last); //результат: own wordnown word 

After all, in principle, the middle had to go beyond the beginning of the container?! ..

Update If the middle iterator goes beyond the container (at first I thought that the compiler doesn’t allow this, i.e. some optimization), what indefinite behavior can influence the result of the next?

 size_t p = ss.size()/4; std::advance(middle, p); while (last != first) *(--middle) = *(--last); //результат: word word unknown 
  • on the idea of ​​not last and the middle must be compared. and why it works - well, apparently so lucky. And the answer is not very similar to the truth (even length). - pavel
  • I think it was not clear expressed. I did the comparison exactly to ask a question, otherwise there are no questions ... - AR Hovsepyan

2 answers 2

Using the end iterator will result in undefined behavior.

However, the list can be built in such a way that the list itself is a node, and thus the list is looped. Abstract example:

 #include <iostream> #include <string> struct list_node_base //Базовый узел, который содержит два указателя на соседние узлы { list_node_base * next; list_node_base * prev; }; template<typename T> struct list_node: list_node_base //Узел целевого типа добавляет данные к базовому узлу { list_node(T const & src): data(src) { } T data; }; template<typename T> struct list: list_node_base //Список является узлом самого себя, но без данных { struct iterator { T & operator*() { return get_pointer()->data; } T * operator->() { return &get_pointer()->data; } bool operator!=(iterator const & rhv) { return p != rhv.p; } list_node<T> * get_pointer() { return static_cast<list_node<T>*>(p); } iterator & operator++() { p = p->next; return *this; } list_node_base * p; }; list(): list_node_base{this, this} {//Список в начальном состоянии состоит из одного узла - самого списка } void push(T const & v) { list_node_base * p = new list_node<T>{T(v)}; prev->next = p;//this->next исправится автоматически при вставке первого элемента p->prev = prev; p->next = this;//Элемент следующий за последним - сам список prev = p; } iterator begin() { return iterator{next};//На первый узел указывает next } iterator end() { return iterator{this};//Сам список и является узлом end } }; int main() { list<std::string> lst; lst.push("some"); lst.push("unknown"); lst.push("word"); auto current = lst.begin(); for(unsigned i = 0; i < 10; ++i) { if (current != lst.end()) {//Чтобы не разыменовать end std::cout << *current << std::endl;//ведь в нем нет члена data } ++current;//Для нашей реализации это валидно даже для end } } 

https://rextester.com/JBC22118

In this list, all nodes except one contain the data member. This "special" node contains the necessary pointers to the first and last elements of the list, and is the basis of the end iterator. Since there is no data member in this node, get_pointer()->data in the iterator will result in undefined behavior.

Such lists are quite simple and easy to implement. The list in gcc is implemented in a similar way:

 //g++ 5.4.0 #include <iostream> #include <string> #include <list> int main() { std::list<std::string> lst; lst.push_back("some"); lst.push_back("unknown"); lst.push_back("word"); auto current = lst.begin(); for(unsigned i = 0; i < 10; ++i) { if (current != lst.end()) { std::cout << *current << std::endl; } ++current; } } 

https://rextester.com/VMNO65384

    The middle iterator will go beyond the container by 9 iterations, so dereferencing it will lead to Undefined Behavior.

    • VTT I updated the question - AR Hovsepyan
    • @ARHovsepyan However, the answer will remain generally the same, only with size_t p = ss.size()/4; the iterator will go out of the container faster. - VTT
    • Well, thanks, I thought what kind of container iterator implementations take place ... - AR Hovsepyan