Search code examples
c++referencevisual-studio-2017g++undefined-behavior

Who's right here? g++ or Visual Studio 2017?


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?


Solution

  • 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.