gpt4 book ai didi

c++ - 高效积累

转载 作者:可可西里 更新时间:2023-11-01 18:07:53 25 4
gpt4 key购买 nike

假设我有字符串 vector ,我想通过 std::accumulate 连接它们。

如果我使用下面的代码:

std::vector<std::string> foo{"foo","bar"};
string res="";
res=std::accumulate(foo.begin(),foo.end(),res,
[](string &rs,string &arg){ return rs+arg; });

我可以很确定会有临时对象构造。

this回答他们说 std::accumulate 的效果是这样指定的:

Computes its result by initializing the accumulator acc with the initial value init and then modifies it with acc = acc + *i or acc = binary_op(acc, *i) for every iterator i in the range [first,last) in order.

所以我想知道避免不必要的临时对象构造的正确方法是什么。

一个想法是以这种方式改变 lambda:

[](string &rs,string &arg){ rs+=arg; return rs; }

在这种情况下,我想我强制有效地连接字符串并帮助编译器(我知道我 shouldn't )省略不必要的拷贝,因为这应该等同于(伪代码):

accum = [](& accum,& arg){ ...; return accum; }

因此

accum = & accum;

另一个想法是使用

accum = [](& accum,& arg){ ...; return std::move(accum); }

但这可能会导致类似的结果:

accum = std::move(& accum);

我觉得这很可疑。

正确的写法是什么来最小化不必要创建临时对象的风险?我不仅对 std::string 感兴趣,我很高兴有一个解决方案,它可能适用于任何已实现复制和移动构造函数/赋值的对象。

最佳答案

我会将其分为两个操作,首先是 std::accumulate 以获得需要创建的字符串的总长度,然后是 std::for_each使用更新本地字符串的 lambda:

std::string::size_type total = std::accumulate(foo.begin(), foo.end(), 0u, 
[](std::string::size_type c, std::string const& s) {
return c+s.size()
});
std::string result;
result.reserve(total);
std::for_each(foo.begin(), foo.end(),
[&](std::string const& s) { result += s; });

常见的替代方法是使用表达式模板,但这不适合作为答案。基本上,您创建一个映射操作但不执行它们的数据结构。当表达式最终被评估时,它可以预先收集它需要的信息并使用它来预留空间并进行复制。使用表达式模板的代码更好,但更复杂。

关于c++ - 高效积累,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19664196/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com