我有一个在std::function
中存储回调的类,然后执行一些操作,然后将结果通知回调目标。如果目标看到结果无效或不想继续进行工作,它将删除包含std::function
回调的调用程序类。
我知道std::function
删除后是否不访问其成员,这将是安全的,但我没有看到这样的保证。我所拥有的是,调用者类在调用回调后不会访问其成员,但是回调可以选择再次执行更多工作,在这种情况下,它不会删除调用者。
此示例说明了问题:
using callback = std::function<void(Caller& c, bool failed)>;
class Caller
{
callback cb;
bool Work()
{
return true;
}
public:
Caller(const callback& cb) : cb{ cb } {}
void DoWork()
{
bool result = Work();
cb(*this, result);
}
};
int main(int argc, char **argv)
{
for (int i = 0; i < 1000; ++i)
{
Caller *c = new Caller{
[](Caller& c, bool failed)
{
if (failed)
delete &c;
else
c.DoWork();
}
};
c->DoWork();
}
}
我使用msvc在Windows上编译了代码,并且可以正常工作(或者可能是隐藏的堆损坏?)
我不希望使用其他设计,因为我正在使用的实际代码很复杂,并且调用方类就像是工作器和回调之间的代理,并且是按操作分配的,因此重构代码会很费劲
编辑:我知道这不是最佳的c + +实践,但我正在处理c api,尤其是iocp。我的代码是这样的:io对象(套接字)发出io请求,该请求需要为重叠的结构和op数据分配内存,该结构将保留回调,当op完成时,它将调用该回调,并且如果有错误,回调可能无法继续进行,否则它将发出下一个请求。调用回调后,结构将自行删除,并且从回调开始的新操作将像这样继续。
现在假设我有一个半双工协议的sessionn,例如http,那么一次只有一个操作,因此我可以对所有操作使用相同的结构,而无需再次分配,因此当第二个操作开始时,我破坏了旧的strucutre并在适当的位置构造新的对象,并在第一个structre的回调中完成]
我有一个在std :: function中存储回调的类,然后执行一些操作,然后将结果通知回调目标。如果目标看到结果无效或不想继续...
看起来不错。我将用指针替换回调中的Caller&
引用,但这并不重要。