测试 std::function 绑定到成员函数后的有效性
test std::function validity after bind to member function
对于结构:
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
均无效。
嗯,这个很简单,用std::shared_ptr
。
当你考虑它时,你基本上想要确保你程序中的某些实体只要有东西在使用它就有效。
换句话说,您正在寻找 shared_ptr
.
否则,设计看起来有点奇怪,如果您程序中的某个实体拥有 a_ptr
,它应该是所有使用此资源的 std::function
的单一所有者,这不是你的意图。如果该所有者不是 std::function
的所有者,您将大大增加分段错误、堆损坏和其他您不想要的东西的可能性。
所以您基本上希望您的函数对象测试由 a_ptr
管理的 A
实例是否存在,我看到使用当前 c++ std 功能执行此操作的 3 种方法。
-- Lambda 引用 unique_ptr
auto a_ptr = std::make_unique<A>();
std::function<void()> f = [&] { if (a_ptr) a_ptr->check(); };
//...later/elsewhere...
f();
这要求指针在函数对象处于活动状态时始终处于活动状态。
-- Lambda 与 shared_ptr
的副本
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();
这需要您的删除器能够以某种方式访问该函数以重置它,无论是直接访问还是通过您 类 中的存储系统访问(函数容器在我看来是一个不错的设计)。
您还可以使用自己的原语创建更复杂的系统,但这会使您离标准库更远。最终,您必须主要根据对象的生命周期和所有权关系来选择最适合您的情况。
对于结构:
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
均无效。
嗯,这个很简单,用std::shared_ptr
。
当你考虑它时,你基本上想要确保你程序中的某些实体只要有东西在使用它就有效。
换句话说,您正在寻找 shared_ptr
.
否则,设计看起来有点奇怪,如果您程序中的某个实体拥有 a_ptr
,它应该是所有使用此资源的 std::function
的单一所有者,这不是你的意图。如果该所有者不是 std::function
的所有者,您将大大增加分段错误、堆损坏和其他您不想要的东西的可能性。
所以您基本上希望您的函数对象测试由 a_ptr
管理的 A
实例是否存在,我看到使用当前 c++ std 功能执行此操作的 3 种方法。
-- Lambda 引用 unique_ptr
auto a_ptr = std::make_unique<A>();
std::function<void()> f = [&] { if (a_ptr) a_ptr->check(); };
//...later/elsewhere...
f();
这要求指针在函数对象处于活动状态时始终处于活动状态。
-- Lambda 与 shared_ptr
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();
这需要您的删除器能够以某种方式访问该函数以重置它,无论是直接访问还是通过您 类 中的存储系统访问(函数容器在我看来是一个不错的设计)。
您还可以使用自己的原语创建更复杂的系统,但这会使您离标准库更远。最终,您必须主要根据对象的生命周期和所有权关系来选择最适合您的情况。