当使用lambda表达式作为回调来确保我的实例保持活动时,我有相当数量的代码依赖于捕获shared_from_this()
:
std::shared_ptr<Thing> self = shared_from_this();
auto doSomething = [this, self] ()
{
// various statements, none of which reference self, but do use this
}
所以问题是:由于我没有在lambda体内引用self
,是否允许一致的编译器优化捕获?
考虑以下计划:
#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
也没有)。
答案 0 :(得分:31)
该标准保证捕获的值不被优化(根据§5.1.2/ 14):
如果隐式捕获实体,并且捕获默认值为=,或者明确是,则按副本捕获实体 使用不包含&amp;的捕获捕获。 对于通过副本捕获的每个实体,未命名的非 静态数据成员在闭包类型中声明。未指定这些成员的声明顺序。 如果实体不是a,则这种数据成员的类型是相应的捕获实体的类型 引用对象,否则引用的类型。
因此,self
被复制到评估的闭包中(根据§5.1.2/ 21):
评估lambda表达式时,复制捕获的实体用于直接初始化 生成的闭包对象的每个对应的非静态数据成员。