问题描述
如果我将nullptr
传递给std::bind
函数,如何检查std::function
的有效性?
// Example program
#include <iostream>
#include <string>
#include <functional>
class A
{
std::string si;
public:
A(std::string s) : si(s) {}
int getData(std::string x) {
si += x;
return si.size(); }
};
A* getA()
{
return nullptr;
}
int main()
{
auto fun = std::bind(&A::getData,getA(),std::placeholders::_1);
if (getA() == nullptr)
std::cout << "nullptr";
std::cout << "output : " << fun("str");
return 0;
}
上面的程序抛出了分割错误。
解决方法
无法访问std::bind
返回的函数对象的绑定参数。
您可以在绑定指针之前检查指针是否为空:
if(A* ptr = getA())
{
auto fun = std::bind(&A::getData,ptr,std::placeholders::_1);
如果实际上需要一个可以从外部访问其绑定参数的函数对象,则需要编写一个命名函数对象类型。例如:
struct Fun {
A* ptr;
int operator()(const std::string& x) {
return ptr->getData(x);
}
};
auto fun = Fun{ .ptr = getA() };
if (fun.ptr)
// is "valid"
,
auto fun = std::bind(&A::getData,getA(),std::placeholders::_1);
您正在将函数对象中的A
实例绑定到nullptr
。因此,分割错误。您应该传递A
(用于第二个参数)的有效实例的地址,该实例的寿命将超过您创建的此函数对象的调用。
无法追溯检查功能对象是否有效。也就是说,在创建它之前,您必须检查指针是否有效。
像这样的事情更有意义:
A a("hello");
auto fun = std::bind(&A::getData,&a,std::placeholders::_1);
或
A* ptr = getA();
if (ptr)
{
auto fun = std::bind(&A::getData,std::placeholders::_1);
...
}
如今,lambda取代了std::bind
来创建函数对象。等价于您正在执行的lambda:
auto fun = [a](std::string str) { return a->getData(str); }
现在为nullptr
使用a
毫无意义。