【发布时间】:2020-07-21 16:37:03
【问题描述】:
我有这个小模板函数来存储我的回调函数以供以后“回调”。
std::function<void(std::string)> stored_callback;
template<class ReadFileCallback, typename Object, class ...T>
void fileMgr_ReadWithCallback(std::string filename, ReadFileCallback callback, Object* object, T ...params) {
std::cout << "fileMgr_ReadWithCallback is processing file: " << filename << std::endl;
stored_callback= [=](std::string s) {
(object->*callback)(s, params...);
};
}
void calledLater() {
stored_callback("somestring");
}
我在这样的课程中使用它:
void MyClass::Read() {
fileMgr_ReadWithCallback("myfile", &MyClass::ReadResult, this, fileId);
}
这很好用,但我非常担心如果 object 失效(超出范围)会导致真正的混乱。
MyClass 可以放入堆中:
MyClass* c=new MyClass();
c->Read(); // callback stored
delete c; // c invalidated
calledLater(); // ???
如果我尝试运行它,它不会导致任何错误。但如果有东西覆盖了c 以前的空间,就会导致可怕的 UB。还是我弄错了?
c 被删除时有什么办法:
-
不拨打
stored_callback,或 -
不致电
(object->*callback)(s, params...);
这对存储一个weak_ptr有好处吗?
stored_callback = [=](std::string s) {
std::weak_ptr<Object> obj = object; //or std::make_shared?
if (auto spt = obj.lock()) (spt->*callback)(s, params...);
};
【问题讨论】:
-
你在寻找std::weak_ptr吗?
-
存储一个
shared_ptr以防止它被破坏,或一个weak_ptr以查明它是否被破坏。或者只是通过编写静态正确的程序来保证它不会被破坏。但是,您无法控制或检查原始指针的生命周期。 -
鉴于上面的
stored_func和lambda表达式,我应该如何修改它来存储object的弱指针? -
用
make_shared分配你的对象,然后使用共享指针来管理它的生命周期(或者当你想跟踪它的生命周期而不让它保持活动状态时使用弱指针)。这非常具有侵入性,因为您正在完全改变所有权模型 -
weak_ptr仅适用于使用shared_ptr管理的对象。您不能使用“普通”对象并期望weak_ptr检测到它何时被销毁。 检测对象是否已被销毁是不可能的,除非您自己以某种方式进行(例如删除对象析构函数中的回调)。
标签: c++ templates lambda variadic-templates