Я смотрю " Не помогите компилятору" поговорить с STL, где у него есть аналогичный пример на слайде 26:
struct A
{
A() = default;
A(const A&) { std::cout << "copied" << std::endl; }
A(A&&) { std::cout << "moved" << std::endl; }
};
std::pair<A, A> get_pair()
{
std::pair<A, A> p;
return p;
}
std::tuple<A, A> get_tuple()
{
std::pair<A, A> p;
return p;
}
std::tuple<A, A> get_tuple_moved()
{
std::pair<A, A> p;
return std::move(p);
}
При этом следующий вызов:
get_pair();
get_tuple();
get_tuple_moved();
Производит этот вывод:
moved
moved
copied
copied
moved
moved
Результат get_pair
построен по ходу движения, что и ожидалось. Движение также может быть полностью отменено NRVO, но оно не соответствует теме настоящего вопроса.
Результат get_tuple_moved
также построен по ходу, что явно указано так. Однако результат get_tuple
копируется, что совершенно неочевидно для меня.
Я думал, что любое выражение, переданное в оператор return
, может считаться неявным move
на нем, поскольку компилятор знает, что он все равно выйдет за рамки. Кажется, я ошибаюсь. Может кто-то уточнить, что здесь происходит?
См. также связанный, но другой вопрос: Когда следует использовать std:: move для возвращаемого значения функции?