Відповіді:
Це безпечно. Const ref продовжує термін експлуатації тимчасових. Областю застосування буде сфера const ref.
Термін експлуатації тимчасового об'єкта може бути продовжений шляхом прив'язки до посилання const lvalue або до посилання rvalue (оскільки C ++ 11), див. Ініціалізацію посилань .
Щоразу, коли посилання прив'язується до тимчасового або до його суб'єкта, термін дії тимчасового подовжується, щоб відповідати терміну експлуатації посилання, за такими винятками :
- тимчасове прив’язане до повернення значення функції у зворотному операторі не розширюється: воно руйнується негайно в кінці виразу повернення. Така функція завжди повертає звисаючу посилання.
- тимчасове прив’язання до посилального члена у списку ініціалізатора конструктора зберігається лише до тих пір, поки конструктор не вийде, не доки об'єкт існує. (зауважте: така ініціалізація неправильно сформована як в DR 1696).
- тимчасовий прив'язок до опорного параметра у виклику функції існує до кінця повного виразу, що містить цей виклик функції: якщо функція повертає посилання, яке переживає повний вираз, воно стає звисаючим посиланням.
- тимчасова прив'язка до посилання в ініціалізаторі, що використовується в новому виразі, існує до кінця повного виразу, що містить цей новий вираз, не так довго, як ініціалізований об'єкт. Якщо ініціалізований об'єкт переживає повний вираз, його референтний член стає звисаючим посиланням.
- тимчасове прив’язання до посилання в еталонному елементі сукупності, ініціалізованого за допомогою синтаксису прямої ініціалізації (дужки) на відміну від синтаксису (дужки) списку-ініціалізації існує до кінця повного виразу, що містить ініціалізатор.
struct A { int&& r; }; A a1{7}; // OK, lifetime is extended A a2(7); // well-formed, but dangling reference
Загалом, термін служби тимчасового не може бути продовжений шляхом "передачі його": друга посилання, ініціалізована з посилання, до якого тимчасовий прив'язується, не впливає на її тривалість життя.
як зазначав @Konrad Rudolph (і див. останній абзац вище):
"Якщо
c.GetSomeVariable()
повертає посилання на локальний об'єкт або посилання на те, що він сам подовжує термін дії якогось об'єкта, продовження терміну дії не починається"
c.GetSomeVariable()
повертає посилання на локальний об'єкт або посилання , що воно саме продовження терміну експлуатації якого - то об'єкта, збільшення терміну експлуатації ніяк НЕ загнутися.
Тут не повинно виникнути жодних проблем, завдяки продовженню терміну експлуатації . Щойно збудований об’єкт протримається до тих пір, поки посилання не вийде за межі.
Це безпечно.
[class.temporary]/5
: Існує три контексти, в яких темпорації руйнуються в іншій точці, ніж в кінці повного виразу . [..]
[class.temporary]/6
: Третій контекст - це посилання на тимчасовий об'єкт. Тимчасовий об'єкт, до якого пов'язується посилання, або тимчасовий об'єкт, який є повним об'єктом суб'єкта, до якого посилається прив'язка, зберігається протягом життя посилання, якщо glvalue, до якого прив'язується посилання, отримано за допомогою одного з наступних : [тут багато речей]
У цьому конкретному випадку це безпечно. Однак зауважте, що не всі часові сховища безпечні для зйомки за допомогою посилання const ... наприклад
#include <stdio.h>
struct Foo {
int member;
Foo() : member(0) {
printf("Constructor\n");
}
~Foo() {
printf("Destructor\n");
}
const Foo& method() const {
return *this;
}
};
int main() {
{
const Foo& x = Foo{}; // safe
printf("here!\n");
}
{
const int& y = Foo{}.member; // safe too (special rule for this)
printf("here (2)!\n");
}
{
const Foo& z = Foo{}.method(); // NOT safe
printf("here (3)!\n");
}
return 0;
}
Посилання, отримане для z
, НЕ БЕЗПЕЧНЕ для використання, оскільки тимчасовий екземпляр буде знищений в кінці повного виразу, перш ніж дійти до printf
заяви. Вихід:
Constructor
here!
Destructor
Constructor
here (2)!
Destructor
Constructor
Destructor
here (3)!