Ответ вслух Middle Указатели и ссылки обновлено

Откуда берутся висячие ссылки

Вопрос

Приведите несколько способов получить висячую ссылку или указатель в C++ и расскажите, как их избегать.

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

Висячая ссылка появляется, когда объект умер, а ссылка или указатель на него ещё используется. Классика: вернуть ссылку на локальную переменную, она уничтожается на выходе из функции.

Что должно прозвучать в ответе

  • Возврат ссылки или указателя на локальную переменную

  • Инвалидация при изменении контейнера: реаллокация vector, erase

  • Временный объект через функцию, возвращающую ссылку (`std::max` с временными)

  • Невладеющие типы (`string_view`, `span`) на умершие данные

  • Захват по ссылке в лямбде, которая переживает область видимости

  • Средства: возврат по значению, явное время жизни, санитайзеры, `-Wdangling-reference`

Что могут спросить следом

  • Почему std::string_view на результат функции, возвращающей std::string, опасен?
  • Какие операции vector инвалидируют итераторы?

Разбор

Висячая ссылка появляется, когда объект умер, а ссылка или указатель на него ещё используется. Классика: вернуть ссылку на локальную переменную, она уничтожается на выходе из функции. Второй источник: контейнеры. После push_back вектор может перевыделить буфер, и все ссылки на элементы виснут; erase инвалидирует всё начиная с удалённого элемента. Третий: временные объекты. Продление жизни работает только при прямой привязке к const&, а const auto& m = std::max(std::string("a"), std::string("b")) висит, потому что max возвращает ссылку на временный аргумент. Четвёртый: невладеющие типы std::string_view и std::span, созданные от временной строки или вектора. Пятый: лямбда, захватившая локальные переменные по ссылке и вызванная позже, например в другом потоке. Избегаю так: возвращаю по значению, не храню ссылки на элементы через изменения контейнера, слежу, кто владеет данными у string_view, захватываю по значению в отложенных лямбдах, гоняю тесты с AddressSanitizer и включаю предупреждения вроде -Wdangling-reference в GCC 14.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.

Термины по теме