Ниже приведен фрагмент кода:
#include <iostream>
using namespace std;
struct B{
int b;
~B(){cout <<"destruct B" << endl;}
};
B func(){
B b;
b.b = 1;
return b;
}
int main(){
const B& instance = (const B&)func(); //is `instance` a dangling reference?
cout <<instance.b<<endl;
return 0;
}
в этом онлайн-компиляторе вывод
destruct B
destruct B
1
Таким образом, возвращаемое значение, похоже, уничтожается раньше, чем операция cout
. Таким образом, instance
кажется оборванной ссылкой.
Если мы изменим const B& instance = (const B&)func();
на const B& instance =func();
, то результат будет
destruct B
1
destruct B
В качестве дополнения, если тестирую код в vs2015, то вывод последний. Однако при тестировании в gcc (до 4.6) вывод будет первым, но вторым в версии после 4.6. Поэтому я хочу знать, ошибается ли онлайн-компилятор или ссылка на самом деле болтается.
(const B&)func()
— это временная ссылка, связанная с временным возвращаемым объектом. Таким образом,instance
привязан к этой временной ссылке, которая является временной. - person scottxiao   schedule 26.05.2018const int& x = (const int&)1; // temporary for value 1 has same lifetime as x
- person cpplearner   schedule 26.05.2018(const B&)func()
не является временным (потому что это lvalue, а не значение prvalue), а в C++ 11 только временные выражения получают продление срока службы. С++ 17 позволяет продлевать время жизни glvalues (для поддержки материализации, я подозреваю), и это, похоже, имело побочный эффект, позволяя вашему приведению, которое теперь приводит glvalue к glvalue (поскольку prvalue уже материализовалось в этот момент ). - person Kerrek SB   schedule 26.05.2018this
в свою диагностику. Это должно оказаться очень информативным. - person Sam Varshavchik   schedule 26.05.2018this
в ваше сообщение позволит вам точно увидеть, какие конкретные экземпляры вашего класса создаются и уничтожаются и когда. - person Sam Varshavchik   schedule 26.05.2018