Когда именно ссылка становится висячей и как продление времени жизни это меняет?
Два из этих трёх случаев оставляют висячую ссылку; один корректен. Определите, какие связываются безопасно, а какие висят, и сформулируйте правило.
#include <string>
const std::string& makeGreeting(const std::string& name) {
return "Hello, " + name;
}
void caseB() {
const std::string& s = std::string("temp");
}
struct Holder { const std::string& ref; };
void caseC() {
Holder h{ std::string("oops") };
}
int main() {
const std::string& g = makeGreeting("world");
}
Найдите и исправьте ошибку.
Ссылка становится висячей, когда объект, с которым она связана, уничтожается, пока ссылка ещё жива — её использование является неопределённым поведением. Привязка const T& к временному объекту продлевает его до области видимости ссылки. Но продление применяется только к прямой привязке: возврат ссылки её не продлевает.
- ✗Возвращать
const T&на локальный или временный объект — продление не переживает возврат - ✗Хранить продлевающую жизнь ссылку в члене структуры и ждать, что временный объект сохранится
- ✗Привязать
const auto& x = vec.front();, затем менятьvec, и реаллокация инвалидируетx
- →Почему привязка через параметр функции не продлевает время жизни временного объекта?
- →Чем висячие ссылки отличаются от висячих указателей по обнаружимости?
Что не так с этим кодом?
#include <string>
// Случай A: возврат ссылки на временный объект
const std::string& makeGreeting(const std::string& name) {
return "Hello, " + name; // временный std::string уничтожается при return
}
// Случай B: продление жизни — работает
void caseB() {
const std::string& s = std::string("temp"); // время жизни продлено
// s валиден до конца caseB()
}
// Случай C: продление НЕ транзитивно
struct Holder {
const std::string& ref;
};
void caseC() {
Holder h{ std::string("oops") }; // временный объект умирает в конце выражения
// h.ref теперь висячая ссылка
}
int main() {
const std::string& g = makeGreeting("world"); // g уже висячая
}
Случай A — ошибка. Конкатенация создаёт временный std::string; продление жизни не применяется к значению, возвращаемому из функции. Временный объект уничтожается, когда makeGreeting возвращает управление, и g в main сразу же висячая.
Случай B — корректно. Привязка const std::string& напрямую к временному объекту продлевает его время жизни до области видимости s.
Случай C — ошибка. Продление применяется к прямой привязке, а не через инициализацию члена. Временный объект, связанный с h.ref, умирает в конце полного выражения, оставляя h.ref висячей.
Правило: продлевает жизнь только прямая привязка const T&/T&& к временному объекту, и только до области видимости самой ссылки. Возврат, параметры функций и члены классов — не продлевают.