C++ 在执行时重新分配std::function对象
我有一个std::function对象,用作某个事件的回调。我正在给这个对象分配一个lambda,在这个对象中,我在执行过程中将对象分配给另一个lambda。当我这样做的时候,我会犯错误。这不是我可以做的吗?若然,原因为何?我将如何实现这一目标 声明:C++ 在执行时重新分配std::function对象,c++,c++11,lambda,std-function,C++,C++11,Lambda,Std Function,我有一个std::function对象,用作某个事件的回调。我正在给这个对象分配一个lambda,在这个对象中,我在执行过程中将对象分配给另一个lambda。当我这样做的时候,我会犯错误。这不是我可以做的吗?若然,原因为何?我将如何实现这一目标 声明: std::function<void(Data *)> doCallback; 任务: doCallback = [=](Data *data) { // // Change the
std::function<void(Data *)> doCallback;
任务:
doCallback =
[=](Data *data)
{
//
// Change the callback within itself because we want to do
// something else after getting one request
//
doCallback =
[=](Data *data2)
{
... do some work ...
};
sendDataRequest();
};
sendDataRequest();
本标准未指定在操作
std::function::operator()
时函数使用其内部状态对象。实际上,一些实现在调用之后使用它
因此,您所做的是未定义的行为,尤其是它崩溃
struct bob {
std::function<void()> task;
std::function<void()> next_task;
void operator()(){
next_task=task;
task();
task=std::move(next_task);
}
}
struct-bob{
功能任务;
std::函数下一个任务;
void运算符()(){
下一个任务=任务;
任务();
任务=标准::移动(下一个任务);
}
}
现在,如果您想更改在
bob()
中下次调用bob
时发生的情况,只需设置next\u task
,标准不会指定函数在std::function::operator()
操作中何时使用其内部状态对象。实际上,一些实现在调用之后使用它
因此,您所做的是未定义的行为,尤其是它崩溃
struct bob {
std::function<void()> task;
std::function<void()> next_task;
void operator()(){
next_task=task;
task();
task=std::move(next_task);
}
}
struct-bob{
功能任务;
std::函数下一个任务;
void运算符()(){
下一个任务=任务;
任务();
任务=标准::移动(下一个任务);
}
}
现在,如果您想更改在
bob()
中下次调用bob
时发生的情况,只需设置next\u任务
简短回答
这取决于(重新)赋值后,被调用的lambda是否访问其任何非静态数据成员。如果是这样,那么您将得到未定义的行为。否则,我相信不会有什么坏事发生
长答案
在OP的示例中,调用由std::function
对象持有的lambda对象(这里用l_1
表示),并在其执行期间将std::function
对象分配给另一个lambda,这里用l_2
表示
赋值调用模板函数&运算符=(F&&F)代码>根据20.8.11.2.1/18,其具有以下效果:
function(std::forward<F>(f)).swap(*this);
函数(std::forward(f)).swap(*this);
其中,f
绑定到l_2
和*此
是分配给的std::function
对象。此时,临时std::函数
保持lu 2
,而*此
保持lu 1
。在swap
之后,临时持有l_1
和*此
持有l_2
(*)。然后临时文件被销毁,l_1
总之,在l_1
上运行operator()
时,此对象将被销毁。然后根据12.7/1
对于具有非平凡构造函数的对象,在构造函数开始执行之前引用该对象的任何非静态成员或基类会导致未定义的行为对于具有非平凡析构函数的对象,在析构函数完成执行后引用该对象的任何非静态成员或基类会导致未定义的行为。
Lambdas非静态数据成员对应其捕获。因此,如果您不访问它们,那么应该可以
还有一个更重要的观点是由的提出的。据我所知,问题是std::function::operator()
,在将调用转发到l_1
后,是否尝试访问l_1
(现在已死亡)?我认为情况并非如此,因为std::function::operator()
的效果并不意味着这一点。事实上,20.8.11.2.4说,这一呼吁的效果是
INVOKE(f,std::forward(args)…,R)
(20.8.2),其中f
是*此
的目标对象(20.8.1)
basicallky说,std::function::operator()
调用l_1.operator()
,并且不做任何其他事情(至少,不做任何可检测的事情)
(*)我将详细介绍交换是如何进行的,但这个想法仍然有效。(例如,如果临时人员持有一份l_1
的副本,而没有指向它的指针怎么办?简短回答
这取决于(重新)赋值后,被调用的lambda是否访问其任何非静态数据成员。如果是这样,那么您将得到未定义的行为。否则,我相信不会有什么坏事发生
长答案
在OP的示例中,调用由std::function
对象持有的lambda对象(这里用l_1
表示),并在其执行期间将std::function
对象分配给另一个lambda,这里用l_2
表示
赋值调用模板函数&运算符=(F&&F)代码>根据20.8.11.2.1/18,其具有以下效果:
function(std::forward<F>(f)).swap(*this);
函数(std::forward(f)).swap(*this);
其中,f
绑定到l_2
和*此
是分配给的std::function
对象。此时,临时std::函数
保持lu 2
,而*此
保持lu 1
。在swap
之后,临时持有l_1
和*此
持有l_2
(*)。然后临时文件被销毁,l_1
总之,在l_1
上运行operator()
时,此对象将被销毁。然后根据12.7/1
对于具有非平凡构造函数的对象,在构造函数开始执行之前引用该对象的任何非静态成员或基类会导致未定义的行为对于具有非平凡析构函数的对象,引用