谁在这里?g ++还是Visual Studio 2017?

pot*_*lad 1 c++ g++ reference undefined-behavior visual-studio-2017

最近,我遇到了一个有趣的“功能”。下面的代码在g ++和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();
}
Run Code Online (Sandbox Code Playgroud)

但是,如果您更改行

auto p = l.front();
Run Code Online (Sandbox Code Playgroud)

auto & p = l.front();
Run Code Online (Sandbox Code Playgroud)

Visual Studio仍然提供相同的输出(当然,考虑到地址x可能会更改)。但是,现在g ++给了我输出

x
x+4
Run Code Online (Sandbox Code Playgroud)

显然,当通过引用传递指针时,g ++会认识到列表的第一个元素现在具有不同的值,这是堆栈的不同地址(与初始地址相比偏移量为4),而Visual Studio 2017则没有。所以...谁伤了?

son*_*yao 5

谁坏了?

两者都是正确的,因为您的代码具有未定义的行为。

之后auto & p = l.front();,您从中擦除了元素list,然后p变得悬垂了;对它的任何取消引用都会导致UB,这意味着一切皆有可能。

对已删除元素的引用和迭代器无效。