绑定到成员函数后测试std :: function validity

时间:2016-01-14 09:01:07

标签: c++ c++11 std-function stdbind

对于struct:

struct A {
    int var = 10;
    void check() {
        std::cout << "var is " << var << std::endl;
    }
};

假设我使用动态分配的A::check()对象创建a的std :: function对象:

auto a_ptr = std::make_unique<A>();
std::function<void()> f = std::bind(&A::check, a_ptr.get());
//...later/elsewhere...
f();

如果我可以测试f以查看绑定的A对象是否仍然存在,那么安全性会很好。是否可以直接从f检索该信息?假设无法从呼叫点访问a_ptr,因此我无法直接对a_ptr进行测试。使用std::function的运算符bool或针对f测试nullptr不起作用。

2 个答案:

答案 0 :(得分:2)

嗯,这个很容易,请使用std::shared_ptr

当你考虑它时,你基本上想要确保你程序中的某个实体只要有东西使用它就有效。
换句话说,您正在寻找shared_ptr

否则,设计看起来有点奇怪,如果程序中的某个实体拥有a_ptr,它应该是使用此资源的所有std::function的单一所有者,而不是你的意图。如果该所有者不是std::function的所有者,则会大大增加分段错误,堆损坏和其他您不想要的内容的可能性。

答案 1 :(得分:2)

所以你基本上希望你的函数对象测试由A管理的a_ptr实例的存在,我看到3种方法用当前的c ++ std特性来做这个。

- Lambda,引用unique_ptr

auto a_ptr = std::make_unique<A>();
std::function<void()> f = [&] { if (a_ptr) a_ptr->check(); };
//...later/elsewhere...
f();

这要求在函数对象处于活动状态时指针仍处于活动状态。

- 带有shared_ptr

副本的Lambda
auto a_ptr = std::make_shared<A>();
std::function<void()> f = [=] { if (a_ptr) a_ptr->check(); };
//...later/elsewhere...
f();

同样的事情,但没有对终身关系的要求,而牺牲一些额外的性能成本,主要是共享指针的副本,可能完全值得在大多数情况下保存的头痛(我将被烧毁这个优化人员。)

- 智能指针中用于重置功能的自定义删除工具

std::function<void()> f;
auto a_ptr = std::unique_ptr<A, std::function<void(A*)>>(new A, [&](A*){ f = nullptr;});
f = std::bind(&A::check, a_ptr.get());
//...later/elsewhere...
a_ptr.reset();
if (f)
  f();

这要求你的删除器可以以某种方式访问​​函数来重置它,无论是直接还是通过类中的存储系统(函数容器都是一个很好的设计imo)。

您还可以使用自己的基元创建更精细的系统,但这会使您远离标准库。最终,您必须根据对象的生命周期和所有权关系选择最适合您情况的东西。