Recently I came across a funny "feature". The code below compiles equally on both g++ and Visual Studio 2017.
#include <iostream>
#include <list>
int main()
{
std::list<int *> l;
int a = 1, b = 2;
l.emplace_back(&a);
auto p = l.front();
std::cout << p << '\n'; // prints x
l.erase(l.begin());
l.emplace_back(&b);
std::cout << p << '\n'; // prints x
std::cin.get();
}
However, if you change line
auto p = l.front();
to
auto & p = l.front();
Visual Studio still gives the same output (considering the address x may change, of course). However, now g++ gives me the output
x
x+4
Obviously, when passing the pointer by reference, g++ recognizes that the first element of the list now has a different value, which is a different address of the stack (offset + 4 compared to the initial one), while Visual Studio 2017 doesn't. So... who's broken?
who's broken?
Both are correct, because your code has undefined behavior.
After auto & p = l.front();
, you erased the element from the list
, then p
becomes dangled; any dereference on it leads to UB, means anything is possible.
References and iterators to the erased elements are invalidated.