Что такое Reference to temporary object? Как продлить время жизни временного объекта?cplus-95

Reference to Temporary Object

Временный объект (temporary) - это объект, созданный в результате:

  • Возврата значения из функции
  • Приведения типов
  • Выражения, не привязанного к переменной

Ссылка на временный объект - это привязка ссылки к такому временному значению.

Опасный пример:

const std::string& badRef = std::string("temporary"); 
// Временный объект уничтожается, ссылка становится висячей

Правила продления времени жизни временных объектов

Стандарт C++ определяет особые случаи, когда время жизни временного объекта продлевается:

1. Привязка к const-ссылке

const std::string& validRef = std::string("Hello"); 
// Время жизни продлено до времени жизни ссылки

2. Привязка к rvalue-ссылке

std::string&& rvalueRef = std::string("Modern"); 
// Также продлевает время жизни

3. Возврат временного объекта из функции

const std::string& getString() {
    return std::string("Safe");  // Время жизни НЕ продлевается - опасность!
}

Способы явного продления времени жизни

1. Сохранение в переменную

auto str = std::string("temporary");  // Копирование
const auto& strRef = str;  // Ссылка на существующий объект

2. Использование std::move

std::string createString() {
    return std::string("Movable");
}
std::string permanent = std::move(createString());  // Перемещение

3. Применение шаблонов perfect forwarding

template<typename T>
void forwarder(T&& arg) {
    // arg сохраняет временный объект
}
forwarder(std::string("Forwarded"));

Ограничения продления времени жизни

  1. Не работает с не-const ссылками:

    std::string& invalid = std::string("temp");  // Ошибка компиляции
    
  2. Не распространяется через возврат из функций:

    const std::string& danglingRef = getString();  // Висячая ссылка!
    
  3. Не применимо к членам класса:

    struct Holder {
        const std::string& ref;
        Holder(const std::string& r) : ref(r) {}
    };
    Holder h(std::string("temporary"));  // ref станет висячей
    

Практический пример

Правильное использование:

const auto& matrix = getTransformationMatrix();  // Время жизни продлено
renderScene(matrix);

Опасная ситуация:

const auto& element = getCollection().front();  // Временная коллекция удаляется
use(element);  // Неопределенное поведение

Резюмируем

  1. Время жизни временных объектов автоматически продлевается только при:

    • Привязке к const-ссылке
    • Привязке к rvalue-ссылке (C++11)
  2. Явные способы продления:

    • Сохранение в переменную
    • Перемещение с std::move
    • Perfect forwarding
  3. Главные опасности:

    • Возврат ссылки на временный объект из функции
    • Хранение ссылок на временные объекты в классах
    • Использование не-const ссылок

Правильное обращение с временными объектами критически важно для написания безопасного и эффективного кода на C++.