是否可以检测绑定成员函数引用的对象是否被删除或销毁

Is it possible to detect if the object that a bound member function refers to is deleted or destroyed

本文关键字:是否 对象 删除 引用 检测 绑定 成员 函数      更新时间:2023-10-16

我正在探索std::functionstd::bind的使用。我看到您可以绑定成员函数,例如:

class A{
    int c_ = 10;
public:
    int add(int a, int b){
        return a + b + c_;
    }
};
int main(){
    A* p_a = new A;
    std::function<int()> f = std::bind(&A::add, p_a, 1, 1);
    printf("%in", f()); // yields "12" (1 + 1 + 10)
    delete p_a;
    printf("%in", f()); // yields derpy numbers, no errors thrown.
}

有没有办法检测p_a是否已被删除?

我的解决方案是拥有一个包装类来保存函数和对象的weak_ptr。我只是想知道是否有更优雅的方法可以做到这一点。

std::bind可以接受智能指针,因此您只需将std::shared_ptr<A>传递给它即可。

std::shared_ptr<A> p_a(new A);
std::function<int()> f = std::bind(&A::add, p_a, 1, 1);
请注意,函

子将拥有该对象:只要函子存在,该对象就会存在。如果您不想要这种行为,那么您带有 weak_ptr 包装器的解决方案很好。

struct A{
  int c_ = 10;
  int add(int a, int b){
    return a + b + c_;
  }
};
template<class T>
std::weak_ptr<T> weak( std::shared_ptr<T> const& sp ) { return {sp}; }
int main(){
  auto p_a = std::make_shared<A>();
  std::function<int()> f = [w_a = weak(p_a)]() {
    if (auto p_a = w_a.lock())
      return p_a->add(1,1);
    throw w_a;
  }
  printf("%in", f()); // yields "12" (1 + 1 + 10)
  p_a.reset();
  try {
    printf("%in", f()); // yields derpy numbers, no errors thrown.
  } catch( std::weak_ptr<A> wp ) {
    printf("object deletedn");
  }
}

活生生的例子。

一般来说,在C++中,您无需为不使用的东西付费。

跟踪对象的生存期是有代价的。 如果要跟踪对象的生存期,可以使用对(免费存储)分配对象的shared_ptrweak_ptr,或者使用对对象拥有的shared_ptr(唯一)的weak_ptr来指示其生存期已结束。

上面是一个使用 C++14 lambda 将对象的共享指针捕获为弱 ptr 的实现,并在已删除时给出定义的行为(抛出所述弱指针的副本)。

生命周期令牌如下所示:

using lifetime_token = std::weak_ptr<void>;
struct has_lifetime {
  has_lifetime():token(std::make_shared<char>()) {}
  has_lifetime(has_lifetime const&o):has_lifetime() {} // not default
  lifetime_token get_lifetime() const {
    return token;
  }
private:
  std::shared_ptr<void> token;
};

has_lifetime 继承会给你一个get_lifetime()成员,只要你存在(它被析构函数销毁,不能再.lock() d)。

如果无法修改原始类的所有权语义,则更容易遵循此模式。 只需.lock()物体的lifetime_token即可确定它是否还活着。