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

时间:2012-12-05 13:56:30

标签: 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);

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

我改为调用_Accumulate函数

string words = _Accumulate(wordArray.begin(), wordArray.end(), 
    move(test), adder);

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

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

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

1 个答案:

答案 0 :(得分:4)

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

  

通过初始化累加器acc初始值init然后计算其结果   对于范围内的每个迭代器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;
}

在你的情况下是不幸的。

选项(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);}
};

请注意,我没有在这里使用rvalue引用返回类型。这是故意的,因为它可以避免悬挂引用问题,例如在拾取最后一个重载并且初始化“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);
  }
};