#c #reference #visual-studio-2017 #g #undefined-behavior
#c #ссылка #visual-studio-2017 #g #неопределенное поведение
Вопрос:
Недавно я наткнулся на забавную «особенность». Приведенный ниже код одинаково компилируется как на g , так и на Visual Studio 2017.
#include <iostream>
#include <list>
int main()
{
std::list<int *> l;
int a = 1, b = 2;
l.emplace_back(amp;a);
auto p = l.front();
std::cout << p << 'n'; // prints x
l.erase(l.begin());
l.emplace_back(amp;b);
std::cout << p << 'n'; // prints x
std::cin.get();
}
Однако, если вы измените строку
auto p = l.front();
Для
auto amp; p = l.front();
Visual Studio по-прежнему выдает тот же результат (конечно, учитывая, что адрес x может измениться). Однако теперь g выдает мне результат
x
x 4
Очевидно, что при передаче указателя по ссылке g распознает, что первый элемент списка теперь имеет другое значение, которое является другим адресом стека (смещение 4 по сравнению с исходным), в то время как Visual Studio 2017 этого не делает. Итак … кто сломался?
Ответ №1:
кто сломался?
Оба верны, потому что ваш код имеет неопределенное поведение.
После auto amp; p = l.front();
того, как вы удалили элемент из list
, он p
становится зависшим; любое разыменование на нем приводит к UB, означает, что возможно все.
Ссылки и итераторы на удаленные элементы недействительны.
Ответ №2:
После того, как l.erase(l.begin());
ссылка на первый элемент, ранее полученный в auto amp; p = l.front();
, становится недействительной, а доступ к значению, хранящемуся в p, приводит к неопределенному поведению. Итак, это ваш код, который поврежден.