ony*_*ony 6 c++ case-study c++11
有人可以描述为什么这段代码不起作用(在从调用返回之前的GCC4.7.3 seg-faults上)?
#include <iostream>
#include <functional>
#include <memory>
using namespace std;
template<typename F>
auto memo(const F &x) -> std::function<decltype(x())()> {
typedef decltype(x()) return_type;
typedef std::function<return_type()> thunk_type;
std::shared_ptr<thunk_type> thunk_ptr = std::make_shared<thunk_type>();
*thunk_ptr = [thunk_ptr, &x]() {
cerr << "First " << thunk_ptr.get() << endl;
auto val = x();
*thunk_ptr = [val]() { return val; };
return (*thunk_ptr)();
};
return [thunk_ptr]() { return (*thunk_ptr)(); };
};
int foo() {
cerr << "Hi" << endl;
return 42;
}
int main() {
auto x = memo(foo);
cout << x() << endl ;
cout << x() << endl ;
cout << x() << endl ;
};
Run Code Online (Sandbox Code Playgroud)
我原来的假设:
std::function<T()>都是对某个表示闭包的对象的引用/ shared_ptr.即捡货价值的生命时间受到限制.std::function<T()> 对象具有赋值运算符,该运算符将放弃旧的闭包(结束生命周期选择的值)并将获得新值的所有权.PS我在阅读关于C++ 11中懒惰的问题后提出了这个问题
这是有问题的代码:
[thunk_ptr, &x]() {
auto val = x();
*thunk_ptr = [val]() { return val; };
return (*thunk_ptr)(); // <--- references a non-existant local variable
}
Run Code Online (Sandbox Code Playgroud)
问题是本地thunk_ptr是上下文的副本.也就是说,在分配*thunk_ptr = ...中thunk_ptr是指由函数对象所拥有的副本.但是,通过赋值,函数对象不再存在.也就是说,下一行thunk_ptr是指刚刚被摧毁的对象.
有几种方法可以解决这个问题:
val.这里的问题是return_type可能是一种引用此方法失败的引用类型.直接从赋值返回结果:在赋值thunk_ptr仍然存在之前,在赋值之后它仍然返回std::function<...>()对象的引用:
return (*thunk_ptr = [val](){ return val; })();
Run Code Online (Sandbox Code Playgroud)安全地复制thunk_ptr并使用此副本来调用return语句中的函数对象:
std::shared_ptr<thunk_type> tmp = thunk_ptr;
*tmp = [val]() { return val; };
return (*tmp)();
Run Code Online (Sandbox Code Playgroud)保存引用的副本std::function并使用它而不是引用属于覆盖闭包的字段:
auto &thunk = *thunk_ptr;
thunk = [val]() { return val; };
return thunk();
Run Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
969 次 |
| 最近记录: |