C++传递std::function参数:传值正常,传指针为何报错?
std::function指针会报错? 这是个很典型的C++类型匹配问题,咱们一步步把逻辑理清楚:
1. 为什么std::function<double(double)> f2 = &fun5;可以正常运行?
std::function是C++标准库提供的函数包装器,它的构造函数专门设计成可以接受兼容的函数指针(或者lambda、仿函数这类可调用对象)。这里fun5是签名为double(double)的函数,对应的指针类型double(*)(double)完全符合std::function<double(double)>的包装要求。
当你写f2 = &fun5时,实际上是调用了std::function的构造函数,自动把函数指针包装成了一个std::function对象,这个类型转换是标准库允许的,所以编译完全没问题。
2. 为什么传&f2会报错?
咱们再看fun1的声明:
double fun1(const double* ang, std::function<double(double)> f1)
它的第二个参数要求的是**std::function<double(double)类型的对象**(这里是值传递,会拷贝对象),而你传递的&f2的类型是std::function<double(double)>*——也就是指向std::function对象的指针,这两个类型完全不兼容。
C++不会自动把对象指针转换成对象本身,因为这涉及完全不同的内存语义:指针是一个内存地址,而对象是实际存储的数据。编译器找不到从std::function*到std::function的隐式转换规则,所以就会抛出你看到的类型转换错误。
额外补充:如果想避免拷贝怎么办?
要是你担心std::function对象拷贝的开销,可以修改fun1的参数为const引用:
double fun1(const double* ang, const std::function<double(double)>& f1)
这时调用fun1(&a, f2)就会传递f2的引用,而不是拷贝整个对象,效率更高。但注意:依然不能传&f2,因为引用是对象的别名,指针是指向对象的地址,两者是完全不同的概念,不能混用。
内容的提问来源于stack exchange,提问作者ee557725

