【问题标题】:Is putting std::move inside a lambda really necessary here?在这里将 std::move 放入 lambda 中真的有必要吗?
【发布时间】:2011-12-15 12:46:47
【问题描述】:

我真的必须将 std::move 调用封装在 lambda 中吗?

std::list<std::wstring>     srcData = GetData(); // implementation not important
std::vector<std::wstring>   dstData;
dstData.reserve(srcData.size());
std::transform(std::begin(srcData), std::end(srcData), std::back_inserter(dstData), 
    [](std::wstring& guid) -> std::wstring { return std::move(guid); });
srcData.clear();

我对 lambdas 和右值引用还是新手,所以最初我尝试过:

std::transform(std::begin(srcData), std::end(srcData), 
    std::back_inserter(dstData), &std::move<std::wstring>);

这不起作用。

我是否必须将移动放在 lambda 中,还是我遗漏了一些明显的东西?

【问题讨论】:

  • 你想达到什么目的?在这种情况下,仅使用 std::copy 或 std::vector<:wstring> dstData(srcData.begin(), srcData.end()) 还不够吗?
  • 第二个。此外,您在没有 lambda 的部分中尝试执行的操作是获取 std::move 的返回值的地址,这与临时的完全一样。获取临时地址总是一个坏主意。
  • @kyku 重点显然是避免复制字符串,而不是移动字符串。根据 std::string 的实现方式,这可能具有很大的性能优势。
  • @Bob 不,这里没有调用 std::move,它的地址正在被占用。这应该是一个函数指针,而不是一个临时地址。

标签: c++ c++11


【解决方案1】:

另一种方法是使用移动迭代器:

std::vector<std::wstring> dstData(std::make_move_iterator(srcData.begin()),
                                  std::make_move_iterator(srcData.end()));

或者使用move算法:

std::move(srcData.begin(), srcData.end(), std::back_inserter(dstData));

既然有人问过,那么您可以通过以下方式强制原始提案生效:

int main()
{
    std::transform(std::begin(srcData),
      std::end(srcData),
      std::back_inserter(dstData),
      static_cast<std::wstring&&(*)(std::wstring&)>(&std::move<std::wstring&>));
}

【讨论】:

  • 诅咒你,当我发现这个问题时,只是发布我想要的内容! :P
  • 好答案+1。但我仍然想知道为什么将std::move&lt;std::wstring&gt; 作为第四个参数传递不起作用,似乎应该这样做。
  • @LokiAstari:您必须选择正确的重载,并提供明确的实例化。我会补充的。
  • 这是我第一次看到移动迭代器。谢谢。
  • @LokiAstari:我认为问题在于模板实例化的选择。问题中的原始尝试使用std::move&lt;std::wstring&gt;,但您实际上需要std::move&lt;std::wstring&amp;&gt;。至于显式实例化,我不明白为什么需要这样做......但我又没有测试它
猜你喜欢
  • 2016-02-22
  • 1970-01-01
  • 2013-06-25
  • 1970-01-01
  • 2019-03-05
  • 2016-02-06
  • 2018-04-05
  • 2021-01-25
  • 1970-01-01
相关资源
最近更新 更多