【问题标题】:push object to vector after passing through conversion function通过转换函数后将对象推送到向量
【发布时间】:2021-01-27 00:19:46
【问题描述】:

我希望插入一个转换函数(可能是一个 std::function)来修改一个被推送到 std::vector 上的对象。我希望对象就地构造,并通过函数而不构造额外的副本。

假设我正在这样做:

std::vector<foo> foo_array;

foo_array.push_back(foo(foo_construct_arguments...));

现在我想这样做:

foo_array.push_back(convert(foo(foo_construct_arguments...)));

“转换”是这样的:

std::function<foo &(foo&)> convert{ [&](foo &f)->foo& { return f; } }

显然,函数必须修改 f 才能有用,但在最简单的情况下,假设它只是返回对象。

我希望得到如下所示的语法:

foo_array.emplace_back(convert(foo(foo_construct_arguments...)));

并且构造了一个 foo 的实例,由 convert 函数修改,然后只用一个构造就放置在向量中。似乎应该有某种方法可以在适当的位置指定 r 值引用来实现这一点,但我对移动语义等还不够熟悉,无法实现。我可以通过 1 个副本找到到达那里的方法。

【问题讨论】:

  • 为什么要把这些都写在一行里?您可以构建对象一次,对其进行修改,然后将其移动到向量中。
  • 有没有办法在没有副本的情况下获取向量中的对象?
  • std::vector::push_back 有一个右值引用的重载,所以如果你为你的对象定义了一个移动构造函数,你可以调用push_back(std::move(modified_obj))
  • 当我这样做时,它会在对象上调用移动、复制、破坏???
  • 由于copy elision,您的代码已经完全按照描述工作。无论如何,您为什么不简单地使用std::transform

标签: c++ move-semantics perfect-forwarding


【解决方案1】:

这里需要的语法是:

std::function<foo&&(foo&&)> convert{[](foo&& f) -> foo&& { return std::move(f); } };

或者,完全通用的 lambda fn

auto fn = [](auto&& f) -> decltype(auto) { return std::forward<decltype(f)>(f); };
std::function<foo&&(foo&&)> convert{fn};

如果此代码在热路径上,您可能希望避免将 lambda 包装到 std::function 中,如果可能的话。


或者,emplace_back 返回对新元素的引用,然后您可以使用它就地修改元素:

std::vector<foo> foo_array;
std::function<void(foo&)> convert{...};
convert(foo_array.emplace_back(foo_construct_arguments...));

【讨论】:

  • 函数签名应该是 std::function???
  • @ttemple 那是另一种选择。
  • 我按照你的方法试了,我收到很多构造/复制调用?
  • @ttemple 您应该尝试优化构建。但是,使用 std::function 会排除内联和复制省略。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多