【问题标题】:Is there a way to detect if object instance is deleted (in lambda)?有没有办法检测对象实例是否被删除(在 lambda 中)?
【发布时间】: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-&gt;*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


【解决方案1】:

有没有办法检测对象实例是否被删除

可以,只要您使用 shared_ptr 管理其生命周期,并在您不想延长生命周期时选择使用 weak_ptr 跟踪它。

对于“非托管”对象(即通过原始指针或具有自动作用域的本地对象直接分配和管理的对象)没有通用的方法。

您无法通过原始指针检测对象是否仍然存在,因为如果它被删除或超出范围,首先取消引用指针是非法的。所以,你必须要么

  1. 编写代码以在原始指针存在时不破坏对象(即静态正确性)
  2. 不使用原始指针,而是使用智能指针(很可能是shared_ptrweak_ptr)来控制对象的生命周期
  3. 让对象在销毁时以某种方式从回调中分离(这是侵入性的,因为现在可以在回调中使用的每个对象都需要知道它)

【讨论】:

    猜你喜欢
    • 2010-11-20
    • 2016-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多