Подтвердить что ты не робот

Время жизни rvalue, привязанное к статической константной ссылке

Рассмотрим это:

std::string foo();

void bar() {
         const std::string& r1 = foo();
  static const std::string& r2 = foo();
}

Я знаю, что время жизни строки, полученной в результате первого вызова foo(), будет распространено на время жизни r1.

Как насчет временной привязки к r2, хотя? Будет ли он жить до конца области или будет ли он оставаться там, когда bar() будет повторно введен?

Примечание. Меня не интересует, делает ли этот конкретный компилятор. (Меня интересует тот, который мы используем, и я могу легко с этим справиться.) Я хочу знать, что стандарт должен сказать об этом.

4b9b3361

Ответ 1

Временное расширение распространяется на время жизни ссылки.

[C++14: 12.2/5]: Временная привязка ссылки или временное, являющееся полным объектом подобъекта, которому привязана ссылка, сохраняется для срока службы ссылки, кроме

  • Временная привязка к ссылочному элементу в конструкторе ctor-initializer (12.6.2) сохраняется до завершения конструктора.
  • Временная привязка к ссылочному параметру в вызове функции (5.2.2) сохраняется до завершения полного выражения, содержащего вызов.
  • Время жизни временной привязки к возвращаемому значению в операторе return функции (6.6.3) не продлевается; временное уничтожается в конце полного выражения в операторе return.
  • Временная привязка к ссылке в new-initializer (5.3.4) сохраняется до завершения полного выражения, содержащего новый-инициализатор. [Пример:

    struct S { int mi; const std::pair<int,int>& mp; };
    S a { 1, {2,3} };
    S* p = new S{ 1, {2,3} }; // Creates dangling reference
    

-end example] [Примечание: это может привести к обманутой ссылке, и в реализациях рекомендуется выпустить предупреждение в таком случае. -end note]

(В частности, обратите внимание, что ни один из пунктов пули не соответствует этому сценарию.)

Итак, в этом случае это существенно, пока программа не закончится.

Мы можем, конечно, проверить это довольно тривиально:

#include <iostream>

struct Tracked
{
    Tracked() { std::cout << "ctor\n"; };
    Tracked(const Tracked&) { std::cout << "copy\n"; };
    ~Tracked() { std::cout << "dtor\n"; };
};

void foo()
{
    static const Tracked& ref = Tracked();
}

int main()
{
    std::cout << "main()\n";
    foo();
    std::cout << "bye\n";
}

Результат:

Основной()
т е р
До свидания
dtor

(живая демонстрация)