c ++使用move而不是copy进行累积

Rol*_*sen 12 c++ visual-c++

我有以下代码

auto adder = [](string& s1, const string& s2)->string&&
   {
      if (!s1.empty())
         s1 += " ";
      s1 += s2;
      return move(s1);
   };

   string test;
   test.reserve(wordArray.size() * 10);
   string words = accumulate(wordArray.begin(), wordArray.end(), 
       move(test), adder);
Run Code Online (Sandbox Code Playgroud)

我想在这里避免字符串复制.不幸的是,这并没有通过vs2012的accumulate实现来实现.内部累积调用另一个函数_Accumulate并且rvalue功能在此过程中丢失.

我改为调用_Accumulate函数

string words = _Accumulate(wordArray.begin(), wordArray.end(), 
    move(test), adder);
Run Code Online (Sandbox Code Playgroud)

我获得了预期的性能提升.

是否必须重写std库以考虑rvalue参数?

还有其他方法我可以使用积累来完成我想要的而不会作弊太多吗?

sel*_*tze 4

检查最近的一份 C++11 草案 (N3337.pdf),我们可以看到 std::accumulate 的效果被指定为

通过使用初始值 init 初始化累加器 acc 来计算其结果,然后按顺序对 [first,last) 范围内的每个迭代器 i 使用 acc = acc + *i 或 acc = binary_op(acc, *i) 修改它。

因此,该标准实际上禁止使用 std::move 作为旧累加器值的实现,如下所示:

template <class InputIterator, class T, class BinOp>
T accumulate (InputIterator first, InputIterator last, T init, BinOp binop)
{
  while (first!=last) {
    init = binop(std::move(init), *first);
    ++first;
  }
  return init;
}
Run Code Online (Sandbox Code Playgroud)

这对你来说很不幸。

选项(1):自己实现这个移动感知积累。

选项(2):继续使用函子,例如

struct mutating_string_adder {
  string operator()(string const& a, string const& b) const {return a+b;}
  string operator()(string & a, string const& b)      const {a += b; return std::move(a);}
  string operator()(string && a, string const& b)     const {a += b; return std::move(a);}
};
Run Code Online (Sandbox Code Playgroud)

请注意,我在这里没有使用右值引用返回类型。这是有意为之,因为它可能会避免悬空引用问题,例如在选择最后一个重载并初始化“a”以引用临时对象的情况下。字符串的所有运算符+重载也有意按值返回。

除此之外,您可能希望将 std::copy 与 std::stringstream 和输出流迭代器结合使用。

附录:mutating_string_adder与部分完美转发交替使用:

struct mutating_string_adder {
  template<class T, class U>
  std::string operator()(T && a, U && b) const {
    return std::move(a) + std::forward<U>(b);
  }
};
Run Code Online (Sandbox Code Playgroud)