Универсальная ссылка как поле класса
У меня есть шаблонная функция принимающая универсальную ссылку. У нее внутри объявлен класс. Реализацию этого класса я опущу. У меня несколько вопросов: будет ли поле data универсальной ссылкой? И не будет ли висячих ссылок?(как я знаю rvalue ссылки продливают время жизни объектов, но в данном случае я не до конца понимаю что будет происходить.)
Сам код:
template<typename Type>
auto fn (Type&& param)
{
class Wrapper
{
public:
Wrapper(Type&& data) : data{std::forward<Type>(data)} {}
public:
Type&& data;
};
return Wrapper{std::forward<Type>(param)};
}
Ответы (2 шт):
Функций fn будет несколько экземпляров, и она универсальна.
Любой объект, хранящий ссылку на rvalue значение должен знать, что после конца команды, ссылка на этот объект неликвидна.
# include <utility>
# include <iostream>
class C{
public:
C(){
std::cout<<this<<"::C()"<<std::endl;
}
~C(){
std::cout<<this<<"::~C()"<<std::endl;
}
};
template<typename Type >
auto fn (Type && param)
{
class Wrapper
{
public:
Wrapper(Type&& data) : data{std::forward<Type>(data)} {}
public:
Type&& data;
};
return Wrapper{std::forward<Type>(param)};
}
int main(){
{ C c1;
auto x1 = fn(c1);
std::cout <<"&x1.data="<<&x1.data<<std::endl; }
auto x2 = fn( C());
std::cout <<"&x2.data="<<&x2.data<<std::endl;
}
0x7ffd1883d24f::C() // c1
&x1.data=0x7ffd1883d24f
0x7ffd1883d24f::~C() // c1
0x7ffd1883d24f::C() // c2
0x7ffd1883d24f::~C() // c2
&x2.data=0x7ffd1883d24f
Временный объект C() создался, команда закончилась. Объект уничтожен. А у вас осталась только память от него. (Ссылка на удалённый объект)
будет ли поле data универсальной ссылкой?
По определению, универсальная ссылка - это rvalue-ссылка на такой тип, который вы даете компилятору определить самостоятельно при создании этой ссылки.
Поэтому, параметр auto fn(Type &¶m) - это универсальная ссылка, но только если вы позволили компилятору определить Type, а не указали его вручную.
А вот параметр Wrapper(Type &&data) и поле Type&& data; - не универсальные ссылки, потому что в обоих случаях Type фиксирован.
Но этим двум и не нужно быть универсальными, ведь внутри функции вы уже знаете, какой у вас аргумент, lvalue или rvalue.
И не будет ли висячих ссылок?(как я знаю rvalue ссылки продливают время жизни объектов
Все ссылки продлевают время жизни объектов, но они делают это ОДИН РАЗ. Если создать одну ссылку из другой, то эта новая ссылка уже ничего не продлевает.
Поэтому вся ваша функция ничего не продлевает.
Если вы напишете fn(MyClass{});, то временный объект будет жить только в этой строчке, до ; (более правильно, "до конца текущего full-expression"). Независимо от того, сохраните вы куда-то Wrapper или нет.