【问题标题】:Avoid double-move when returning a pair in C++在 C++ 中返回一对时避免双重移动
【发布时间】:2020-11-12 21:37:50
【问题描述】:

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

#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;
}

但是,当我运行它时,我看到A8 构造的双重移动:

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

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

【问题讨论】:

  • 我可能必须指定 a 的构造在示例中过于简单。这实际上是一个相当大的过程,包括需要对已经构建好的版本进行操作。
  • return {move(a), 10}; 有问题吗?如果您可以更新问题以显示行为比预期更差的代码,那就太好了
  • 哦,您正在使用(U1&amp;&amp;, U2&amp;&amp;)-constructor,它也应该可以工作。好想法!我认为当A 的构造函数接受多个参数时,这种情况开始中断......

标签: c++ tuples move-constructor


【解决方案1】:

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

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

Demo

所以你有std::tuple&lt;A&amp;&amp;&gt; 而不是std::tuple&lt;A&gt;(移动构造)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-31
    • 1970-01-01
    • 1970-01-01
    • 2019-09-03
    • 2019-07-25
    相关资源
    最近更新 更多