Кто здесь? g ++ или Visual Studio 2017? - PullRequest
1 голос
/ 23 марта 2019

Недавно я наткнулся на забавную «фишку». Приведенный ниже код одинаково компилируется как в 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 ]

5 голосов
/ 23 марта 2019

кто сломан?

Оба верны, потому что ваш код имеет неопределенное поведение.

После auto & p = l.front(); вы стерли элемент из list, затем p становится повисшим; любая ссылка на него ведет к UB, означает, что все возможно.

Ссылки и итераторы на стертые элементы недействительны.

4 голосов
/ 23 марта 2019

После l.erase(l.begin()); ссылка на первый элемент, ранее полученный в auto & p = l.front();, становится недействительной, а доступ к значению, сохраненному в p, приводит к неопределенному поведению.Так что ваш код не работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...