C++:可以优化未使用的lambda显式捕获吗?

Tra*_*kel 25 c++ lambda language-lawyer c++11

我有相当数量的代码,它依赖于捕获shared_from_this()当使用lambda表达式作为回调时确保我的实例保持活动状态:

std::shared_ptr<Thing> self = shared_from_this();
auto doSomething = [this, self] ()
{
    // various statements, none of which reference self, but do use this
}
Run Code Online (Sandbox Code Playgroud)

所以问题是:由于我没有self在lambda体内引用,是否允许一致的编译器优化捕获?


考虑以下程序:

#include <functional>
#include <iostream>
#include <memory>

std::function<void ()> gFunc;

struct S : std::enable_shared_from_this<S>
{
    void putGlobal()
    {
        auto self = shared_from_this();
        gFunc = [self] { };
    }
};

int main()
{
    auto x = std::make_shared<S>();
    std::cout << x.use_count() << std::endl;
    x->putGlobal();
    std::cout << x.use_count() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

输出是:

1
2
Run Code Online (Sandbox Code Playgroud)

这表明g++-4.7.1不会优化捕获(也不会clang-3.1).

Tra*_*kel 33

该标准保证捕获的值不会被优化(根据§5.1.2/ 14):

如果隐式捕获实体并且捕获默认值为=,或者使用不包含&的捕获显式捕获实体,则通过副本捕获实体.对于由副本捕获的每个实体,在闭包类型中声明未命名的非静态数据成员.这些成员的声明顺序未指定.如果实体不是对对象的引用,则这种数据成员的类型是对应的捕获实体的类型,否则是引用的类型.

因此,self在评估时被复制到关闭中(根据§5.1.2/ 21):

在计算lambda表达式时,复制捕获的实体用于直接初始化生成的闭包对象的每个对应的非静态数据成员.

  • @GManNickG:区别在于隐式捕获(`[=]`)和*explicit*capture(`[someNameHere]`).隐式捕获需要使用ODR元素.显式捕获不会. (9认同)