【发布时间】:2021-09-22 18:39:30
【问题描述】:
这是一个简单的向量和类的过度简化的代码。
class OutputClass
{
public:
OutputClass(int x, int y);
};
std::vector<OutputClass> Convert(std::vector<int> const &input)
{
std::vector<OutputClass> res;
res.reserve(input.size());
//either (1)
for (auto const &in : input)
res.emplace_back(in, in*in);
return res;
//or something like (2)
std::transform(input.begin(),
input.end(),
std::back_inserter(res),
[](InputClass const &in){return OutputClass(in, in*in);});
return res;
}
这两个选项的性能有区别吗?静态分析器通常具有用算法替换所有原始循环的规则,但在这种情况下,在我看来,使用 emplace_back 循环会更有效,因为我们不需要复制或移动。或者我错了,它们在性能方面是相同的,(2)在良好的风格和可读性方面更可取?
【问题讨论】:
-
Is there difference in performance in those two options?你可以通过测量找到。 -
除非有
back_emplacer,否则我会使用循环来放置和插入算法。它们表达的东西略有不同,即使经过优化后它们可能是相同的 -
刮掉我的最后一条评论。我在C++ Quick Bench 上再次运行了替补席,
emplace_back版本稍微快了一点。当我最初运行测试时,我忘记了std::vector中的reserve空间用于std::transformbench -
@WBuck 如果您声称有一些基准测试结果并链接quick-bench.com,为什么不包含指向您的结果的链接?我无法可靠地重现
emplace_back比std::transform快:quick-bench.com/q/SoJQbRCSrkd5z2Kd04kh-S6jUkE -
std::transform 允许您从 C++17 开始指定执行策略,允许您并行执行。可悲的是,它似乎不适用于 std::back_inserter。在对此进行试验时,我偶然发现了一个事实,对于您的简单示例,
resize+ 填充的速度是reserve+ 插入的两倍。程序集显示 clang12 和 gcc10 无法矢量化插入循环——也许它们无法证明不需要调整大小? quick-bench.com/q/yKgW89g_4Q0GhYtTWIxPqs_Kzzc。 (注意:它运行的容器可能被限制为一个核心)
标签: c++ algorithm performance c++11 std