问题描述
请帮助您检查以下代码?如果本地std :: function超出其“寿命”,会有什么问题吗?预先感谢。
class Test {
public:
void commit(std::function<void()> func)
{
// return immediately
dispatch_async(conqueue,^{
// in order to call func when it is out of "life"
sleep(5);
func(); // is there any issue? the func should be invalid at this moment?
});
}
void test() {
std::string name = "test";
std::function<void()> func = [name,this] () {
printf("%lx %s\n",&name,name.c_str());
std::cout << "callback"<<std::endl;
};
// async
commit(func);
}
//...
};
解决方法
好的,我进行了一些测试,并改变了对此的看法。该代码是安全的,因为func
是按值捕获的(即该块继承了一个副本)。
我通过以下测试程序向我证明了这一点(您将需要MacOS来运行它):
// clang block_test.mm -lc++
#include <iostream>
#include <unistd.h>
#include <dispatch/dispatch.h>
struct Captured
{
Captured () {}
Captured (const Captured &c) { std::cout << "Copy constructor\n"; }
void Foo () const { std::cout << "Foo\n"; }
};
int main ()
{
Captured c;
// return immediately
dispatch_async (dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
sleep(5);
c.Foo ();
});
sleep (10);
};
输出:
Copy constructor
Copy constructor
Foo
我不确定为什么复制构造函数被调用两次。问苹果。
更新:关于使用块here的文章很好。那就是那个有趣的“帽子”语法。
,很安全。 Apple“块”通过值捕获非__block
变量,因此该块内部包含std::function
的副本,因此该块的变量副本的生存期与该块本身相同。
(PS即使该变量被声明为__block
,它仍然是安全的。在多个块中,块捕获__block
变量的类型是“通过引用”,以及原始功能范围共享变量的状态,但是__block
的基础机制确保了变量被超出函数作用域的块使用时,将其移到堆中。因此,对于__block
变量,它的寿命将一直持续到捕获它的所有块都被破坏为止。)