-4

create a list:

list<int> l;
auto it = l.begin();
l.emplace(it, 0);
/*it =*/ l.emplace(it, 1);
/*it =*/ l.emplace(it, 2);

here to print

for (auto it : l)
    cout << it << endl; // 0 1 2
cout << "\n\n";
cout << *it << endl; // = 3

Why is *it 3 and not 0?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 5
    `auto it = l.begin()` makes `it` a past-the-end iterator. You cannot dereference a past-the-end iterator. – Raymond Chen Jul 13 '22 at 19:05
  • 3
    The `it` in your `for` loop has no connection to the `it` above. It's a different type, and refers to a different thing. (Despite the name, the `it` in your `for` loop is an `int`, not an iterator.) – Nathan Pierson Jul 13 '22 at 19:06
  • `l.begin()` is an iterator to a specific element, the element that was the first in the list *at the time it was called*. At that time, the list was empty. Calling `begin` on an empty range is the same as calling `end`, it's a one-past-the-end iterator. This is so things like `std::distance` and `for` loops work exactly the same way for empty and non-empty ranges. – François Andrieux Jul 13 '22 at 19:12
  • If you are using the compiler gcc or clang, then I suggest that you compile with `-Wshadow`. That way, the compiler will warn you in situations in which one variable shadows a different variable with an identical name, as is the case with the variable `it` in your case. You may want to read this: [Why should I always enable compiler warnings?](https://stackoverflow.com/q/57842756/12149471). Note that the compiler options `-Wall` and `-Wextra` do not include `-Wshadow`, you must specify this explicitly. – Andreas Wenzel Jul 13 '22 at 19:51

1 Answers1

2

At this line:

auto it = l.begin();

There is nothing in the list yet, so the beginning is also the end.

std::list::emplace() inserts items before the given iterator, so this line:

l.emplace(it, 0);

Places 0 before it, ie it inserts at the end of the list.

std::list also has some of the most forgiving iterator invalidation rules, and the it iterator is not invalidated as items are inserted into the list. it continues to refer to the end of the list as new items are added to the list.

Ultimately, this line:

cout << *it << endl;

Dereferences the "end" iterator, and this is not allowed. The results are undefined, and in this case it appears to contain the value 3. Maybe if you add another item then it'll appear to contain 4, and maybe you're seeing a hidden implementation-specific detail of the list. Or maybe the computer will crash or get a bad case of the nasal demons.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
user4581301
  • 33,082
  • 7
  • 33
  • 54