Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 是否可以检测绑定成员函数引用的对象是否被删除或销毁_C++_Function_Pointers_Bind - Fatal编程技术网

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

C++ 是否可以检测绑定成员函数引用的对象是否被删除或销毁,c++,function,pointers,bind,C++,Function,Pointers,Bind,我正在探索使用std::function和std::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);

我正在探索使用
std::function
std::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("%i\n", f()); // yields "12" (1 + 1 + 10)
    delete p_a;
    printf("%i\n", f()); // yields derpy numbers, no errors thrown.
}
A类{
int c_=10;
公众:
整数相加(整数a,整数b){
返回a+b+c;
}
};
int main(){
A*p_A=新的A;
函数f=std::bind(&A::add,p_A,1,1);
printf(“%i\n”,f());//产生“12”(1+1+10)
删除p_a;
printf(“%i\n”,f());//生成derpy数字,没有抛出错误。
}
有没有办法检测p_a是否已被删除


我的解决方案是使用一个保存函数的包装器类和对象的
弱ptr
。我只是想知道是否有更优雅的方法来实现这一点。

std::bind
可以接受智能指针,因此您只需将
std::shared\u ptr
传递给它即可

std::shared_ptr<A> p_a(new A);
std::function<int()> f = std::bind(&A::add, p_a, 1, 1);
std::共享ptr p_a(新a);
函数f=std::bind(&A::add,p_A,1,1);
请注意,函子将拥有该对象:该对象将一直存在。如果您不希望出现这种行为,那么使用
弱\u 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("%i\n", f()); // yields "12" (1 + 1 + 10)
  p_a.reset();
  try {
    printf("%i\n", f()); // yields derpy numbers, no errors thrown.
  } catch( std::weak_ptr<A> wp ) {
    printf("object deleted\n");
  }
}
继承自
的has_life
将为您提供一个
get_life()
成员,该成员将在您执行此操作时一直存在(它将被析构函数销毁,并且不再是
.lock()
d)


如果不能修改原始类的所有权语义,那么这是一种更容易遵循的模式。只需
.lock()
对象的
生命周期标记
,即可确定其是否仍然处于活动状态。

您可以使用智能指针(而不是原始指针),特别是:
std::shared_ptr
std::weak_ptr
。无法检测指针何时被删除。您应该避免创建对象不知道它想要访问的其他对象是否仍然处于活动状态的情况。智能指针是这里的方法。@πάνταῥεῖ 因此只要
std::function
存在,对象就会存在?@MichaelMitchell我的想法是
std::weak\u ptr
用于
std::bind()
,您可以在调用
f()
之前检查它。当然,您也可以绑定
shared\u ptr
,它将保证
A
的生命周期不早于
f
在范围内结束。因此,如果
std::bind
被传递
shared\u ptr
只要函数存在,
shared\u ptr
中的对象就不会被删除?你的编辑回答了这个问题。根据我的包装器类想法,如果我想让一个类绑定它的一个函数,我是否必须从启用共享,以便向包装器传递适当的
弱ptr
。这是this@MichaelMitchell中的
共享\u的经典用例。如果在某些类方法中无法获得指向此的智能指针,则必须使用this
中的
启用共享\u。请注意,如果绑定发生在类之外,则不必这样做。
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;
};