lambda函数中按引用/值捕获的成本?

Vin*_*ent 4 c++ optimization lambda pass-by-reference c++11

请考虑以下代码:

#include <iostream>
#include <algorithm>
#include <numeric>

int main()
{
    const unsigned int size = 1000;
    std::vector<int> v(size);
    unsigned int cst = size/2;
    std::iota(v.begin(), v.end(), 0);
    std::random_shuffle(v.begin(), v.end());
    std::cout<<std::find_if(v.begin(), v.end(), [&cst](const int& i){return i == cst;})-v.begin()<<std::endl;
    std::cout<<std::find_if(v.begin(), v.end(), [=](const int& i){return i == cst;})-v.begin()<<std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

此代码使用值填充向量,对其进行混洗,然后搜索指定值的索引(这只是一个示例来说明我的问题).cst可以通过引用或lambda函数中的值捕获此值.

我的问题:两个版本之间的性能是否存在差异,或者它们是否会被编译器以相同的方式进行优化?

通过引用传递常量基本类型和通过引用传递常量类是一个很好的规则(就像在普通函数中一样)?

kun*_*sch 6

在实践中,小型没有性能差异.

随着clang -O3我得到了这两种情况下相同的代码.没有优化会clang生成不同的代码,复制版本恰好是一个较小的指令.

$ clang ref.cpp -O3 -std=c++11 -S -o ref.s
$ clang cpy.cpp -O3 -std=c++11 -S -o cpy.s
$ diff ref.s cpy.s
Run Code Online (Sandbox Code Playgroud)

存在与const相关的小差异.

复制捕获为您提供了一个const unsigned值.这不会编译:

unsigned cst = 123;
[=](const int& i){ return i == ++cst; }
Run Code Online (Sandbox Code Playgroud)

非const变量的引用捕获导致非const unsigned&引用.这会将原始值修改为副作用:

unsigned cst = 123;
[&](const int& i){ return i == ++cst; }
Run Code Online (Sandbox Code Playgroud)

作为一个好的规则,应该避免复制大对象.如果小对象在lambda范围内应该是常量,但在当前范围内不是常量,则copy-capture是一个不错的选择.如果lambda的生命周期超过本地对象的生命周期,则复制捕获是唯一的选择.

  • 恭喜无聊并且给了你一个有人必须接受这个问题的upvote (2认同)