测试标准::绑定到成员函数后的函数有效性

test std::function validity after bind to member function

本文关键字:函数 有效性 标准 绑定 测试 成员      更新时间:2023-10-16

对于结构:

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

假设我使用动态分配的 a 对象创建了一个 A::check() 的 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或针对nullptr测试f是行不通的。

所以你基本上希望你的函数对象测试a_ptr管理的A实例是否存在,我看到 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)。


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

嗯,这个很简单,使用 std::shared_ptr .

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

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