首页 > 解决方案 > 在 C++ 中用 lambda 替换函数

问题描述

我有一个函数,它只是将值 1 设置为 struct member variable length。在现代 C++ 中,这似乎不是好的代码风格。这可以用 lambda 完成吗?

void setEdgeLengths(Koala::AssocArray <koalaGraph::PEdge, Koala::DijkstraHeap::EdgeLabs<int >> &edgeMap, std::vector<koalaGraph::PEdge>& E) 
{
    for (size_t i = 0; i < E.size(); i++) {
    edgeMap[E[i]].length = 1;
    }
}

我问的原因是https://shaharmike.com/cpp/lambdas-and-functions/表明 lambda 将比普通函数更快。

Lambda 在性能方面也很棒。因为它们是对象而不是指针,所以编译器可以很容易地内联它们,就像函子一样。这意味着多次调用 lambda(例如使用 std::sort 或 std::copy_if)比使用全局函数要好得多。这是 C++ 实际上比 C 快的一个例子。

标签: c++lambda

解决方案


我会认为以下代码是最佳的(除了给定的变量名):

void setEdgeLengths(Koala::AssocArray <koalaGraph::PEdge, Koala::DijkstraHeap::EdgeLabs<int >> &edgeMap, std::vector<koalaGraph::PEdge>& E) 
{
    for (const auto& e : E) {
        edgeMap[e].length = 1;
    }
}

随心所欲地设计(或省略)花括号。

您可以将任何或所有这些放入任意多个嵌套的 lambda 中,但这并不比添加更多空白更有用(但可能更有害,至少在调试版本中)。你可能想问的是:

void setEdgeLengths(Koala::AssocArray <koalaGraph::PEdge, Koala::DijkstraHeap::EdgeLabs<int >> &edgeMap, std::vector<koalaGraph::PEdge>& E) 
{
    std::for_each(E.begin(), E.end(), [&edgeMap](const auto& e) {
        edgeMap[e].length = 1;
    });
}

您不再有一个简单的循环(有些人提倡这种良好的风格),但我认为代码并没有变得更清晰。这样做也没有变得更快 - 如果有的话,调试性能可能会略有降低。

现在,后一种形式确实允许并行执行

std::for_each(std::execution::parallel, E.begin(), E.end(), [&edgeMap](const auto& e) {

但这只有在您edgeMap正确处理并发访问时才合法。如果它是std::map,operator[]可能会插入一个新元素(它不是线程安全的),因此如果没有进一步的假设,这将不是合法的优化。


推荐阅读