在 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)};
所以你有 std::tuple<A&&>
而不是 std::tuple<A>
(移动构造)。
我正在尝试编写一个 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)};
所以你有 std::tuple<A&&>
而不是 std::tuple<A>
(移动构造)。