在 C++ 中返回一对时避免双重移动

Avoid double-move when returning a pair in C++

我正在尝试编写一个 returns 一对对象的函数,其中一个比另一个更难构造。此代码接近说明我正在尝试的内容:

#include<iostream>
#include<tuple>

using namespace std;

struct A {
  int i;
  A(A&& a): i(a.i) { cout << "move-constructing A: "<<a.i<<"\n"; }
  A(int j): i(j) { cout << "int-constructing A: "<<j<<"\n"; }
};
using APair = pair<A,A>;

APair get_As() {
  A a(8);
  return {piecewise_construct, make_tuple(move(a)), make_tuple(10)};
}

int main()
{
  APair As = get_As();
  return 0;
}

但是,当我 运行 这样做时,我看到 A 的双重移动 8:

int-constructing A: 8
move-constructing A: 8
move-constructing A: 8
int-constructing A: 10

我发现那是因为 A 移到了 std::tuple,然后移到了 main()APair。显然,一次移动就足以构造 APair,但我不知道该怎么做,因为分段构造函数似乎是不可避免的,这意味着我还必须提供一个元组......因此我的问题是: 这怎么能用 A 的一步来完成?

您可以使用 std::forward_as_tuple 来避免额外的移动构造函数:

return {piecewise_construct, std::forward_as_tuple(move(a)), make_tuple(10)};

Demo

所以你有 std::tuple<A&&> 而不是 std::tuple<A>(移动构造)。