我有以下代码
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参数?
还有其他一些方法可以使用累积来完成我想要的而不会作弊太多吗?
答案 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);
}
};