CXX95 Telegram 23
#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, ссылка была рабочей, а вот потом объект разрушился и ссылка стала висячей. Дебаг занял достаточно много времени...
🔥5🤯2



tgoop.com/cxx95/23
Create:
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

View MORE
Open in Telegram


Telegram News

Date: |

Channel login must contain 5-32 characters Avoid compound hashtags that consist of several words. If you have a hashtag like #marketingnewsinusa, split it into smaller hashtags: “#marketing, #news, #usa. A Telegram channel is used for various purposes, from sharing helpful content to implementing a business strategy. In addition, you can use your channel to build and improve your company image, boost your sales, make profits, enhance customer loyalty, and more. Clear How to build a private or public channel on Telegram?
from us


Telegram C++95
FROM American