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

时间:2019-03-23 14:20:59

标签: c++ reference visual-studio-2017 g++ undefined-behavior

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

但是,如果您换行

auto p = l.front();

auto & p = l.front();

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

x
x+4

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

2 个答案:

答案 0 :(得分:5)

  

谁坏了?

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

auto & p = l.front();之后,您erased list中的元素,然后p变成了悬空;任何对其的取消引用都将导致UB,这意味着一切皆有可能。

  

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

答案 1 :(得分:4)

$ bundle init Writing new Gemfile to /private/var/folders/_2/rg7rz1h56sb2ln5f75gjr7558b1wz3/T/tmp.PPIvZRXi/Gemfile $ echo "gem 'ohai'" >> Gemfile $ bundle install --path vendor/gems --jobs 4 ... 之后,对先前在l.erase(l.begin());获得的第一项的引用变得无效,并且访问存储在p中的值将导致未定义行为。所以是您的代码被破坏了。