28

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

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

所以问题是:由于我没有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;
}

输出是:

1
2

这表明g++-4.7.1没有优化捕获(也没有clang-3.1)。

4

1 回答 1

34

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

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

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

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

于 2012-10-03T23:42:41.290 回答