tgoop.com/cxx95/23
Create:
Last Update:
Last Update:
#creepy
Reference Lifetime Extension
Сегодняшнее "стрёмное правило стандарта": если вы инициализируете константную ссылку (const T&
) "временным объектом" (скорее всего rvalue
), то этот временный объект не уничтожается как ему было положено, а продолжает жить ровно столько, сколько живет ссылка.
Пример в двух строках:
std::string Foo::GetName();
const std::string& name = obj.GetName(); // легально и не сломается
Наверное, самое популярное использование этого правила - дефолтные значения ссылочных аргументов
void foo(const std::string& s = "default_text");
Это правило супер легко сломать - как только вызовете метод у временного объекта (
obj.GetName().data()
), или если будет сделан неявный каст, и так далее.Abseil Tip of the Week показывает больше примеров успеха и фейла.
В моем примере наличие этого правила допустило лютый баг:
class A { ... };
class B : public A { ... };
void foo(const A& a) { ... }
void foo(const B& b) {
// ...
foo(static_cast<A>(b));
}
Я сделал неправильный каст, который скопировал объект, а не скастил к базовому классу. Правильный каст -
static_cast<const A&>(b)
.Выстрел в ногу произошел, когда
foo(const A& a)
стал сохранять ссылку на a
, чтобы потом её переиспользовать. Пока вызывался foo
, ссылка была рабочей, а вот потом объект разрушился и ссылка стала висячей. Дебаг занял достаточно много времени...BY C++95
Share with your friend now:
tgoop.com/cxx95/23