以下代码抛出异常
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::bad_function_call> >'
what(): call to empty boost::function
在第f()
行(执行块时):
void foo(); // assume this is defined somewhere
boost::function<void()> f = boost::bind(&foo);
^(void) {
f();
}();
然而,根据the documentation on blocks,
通常,您可以在块中使用C ++对象。在成员函数中,对成员变量和函数的引用是通过隐式导入的this指针,因此看起来是可变的。如果复制块,则有两个注意事项:
如果你有一个基于堆栈的C ++对象的__block存储类,那么就会使用通常的复制构造函数。
如果在块中使用任何其他基于C ++堆栈的对象,则它必须具有const复制构造函数。然后使用该构造函数复制C ++对象。
这似乎是正常的;如果我将上面的f
替换为带有operator()()
的简单类的实例,则上述代码将按预期运行。
为什么带boost::function
的版本不起作用?
答案 0 :(得分:1)
如果我使用__block
修改声明,它似乎正常工作:
__block boost::function<void()> f = boost::bind(&foo);
我仍然不确定为什么会这样 - 正如@Richard在上面的评论中提到的那样,它必须与“const拷贝构造函数”有关,而不是“通常的拷贝构造函数”。不过,我不知道如何检查这种差异;以下工作正常:
const boost::function<void()> f = boost::bind(&foo);
const boost::function<void()> g(f);
g();
如果那不调用“const拷贝构造函数”,我不确定会发生什么。
答案 1 :(得分:0)
你的答案中的例子,
const boost::function<void()> f = boost::bind(&foo);
const boost::function<void()> g(f);
g();
有效,因为您在创建其被调用者的同一范围内调用operator()
。 f()
也可以在块作用域之外工作,并且调用foo()
将在块作用域内工作,因为它是一个经典函数,并且在调用时不被视为“已修改”。在将包含范围的对象传递给块范围时,会引用对 const复制构造函数的引用调用。似乎 const复制构造函数中存在的任何差异都无法将对象的一部分复制到块作用域。