Может кто-нибудь объяснить порядок выполнения этого кода?
struct Foo {
~Foo() {
std::cout << "1";
}
};
int main() {
const Foo& bar = Foo();
const Foo& baz = std::move(Foo());
std::cout << "2";
}
Следующий код печатает 121
.
Я понимаю, почему я получаю 1 после 2, потому что время жизни объекта привязано к блоку кода, в котором он выполняется, и я также знаю, что rvalue может привязываться к константной ссылке lvalue, но почему деструктор перемещенного объекта вызывается немедленно? В чем причина этого? Где именно вызывается этот деструктор?
К сожалению, ни GCC, ни Clang не предупреждают (напрямую) о проблеме. Они оба предупреждают о том, что baz
не используются, но не жалуются на bar
, поскольку разрушение имеет побочные эффекты, что является косвенным признаком, но не является хорошим объяснением :(
@molbdnilo: это временный объект. Причина отсутствия продления времени жизни заключается в том, что ссылка не привязана «напрямую» к временному объекту.
std::move
имеет параметр ссылки на пересылку t
, который привязывается к значению prvalue Foo()
. Затем, когда эта функция возвращается, этот временный объект уничтожается, давая нам упомянутый результат.
По сути, временное значение привязано к параметру t
вместо baz
//-------------------------------------------------------------------v------------> Foo() is bound to this parameter
template< class T > constexpr std::remove_reference_t<T>&& move( T&& t ) noexcept;
Он уничтожается не при возврате функции, а позже, когда завершается выполнение выражения инициализатора.
В std::move(Foo());
объект Foo
привязан к параметру функции перемещения, а не к baz
.
И когда функция возвращается, временная уничтожается.
std::move(Foo())
(он жеstatic_cast<Foo&&>(Foo())
не является временным объектом; привязка к нему константной ссылки не продлевает его время жизни. Ссылка rvalue — это не то же самое, что rvalue.