有没有一种方法可以检测是否删除了对象实例(在lambda中)?

时间:2020-07-21 16:37:03

标签: c++ templates lambda variadic-templates

我有这个小的模板函数来存储我的回调函数,以便以后进行“回调”。

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...);
};

1 个答案:

答案 0 :(得分:1)

有没有一种方法可以检测对象实例是否被删除

是的,只要您使用shared_ptr管理其寿命,并且在不想延长该寿命的情况下可以选择使用weak_ptr对其进行跟踪。

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

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

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