如何避免取标准库函数地址时的非标准行为?
解决取标准库函数地址的未定义行为问题
标准库中大部分函数(比如std::sqrt)的地址不能直接获取,这属于未定义行为——因为标准允许实现对这些函数提供重载、inline特化或者其他优化,直接取地址可能导致编译或运行时的意外问题。针对你的代码,有两种简单的修正方案:
方案一:用自定义包装函数封装标准库函数
自己写一个简单的包装函数,内部调用标准库函数,然后取这个自定义函数的地址即可:
#include <iostream> #include <vector> #include <cmath> bool divisible_3(double n){ return static_cast<int>(n) % 3 == 0; } // 包装std::sqrt的自定义函数 double sqrt_wrap(double x) { return std::sqrt(x); } void applyFunction(std::vector<double>& vector, bool(* filterf)(double), double(*calc)(double)){ for(size_t index = 0; index < vector.size(); index++){ // 用size_t替代int更规范 if(filterf(vector[index])){ vector[index] = calc(vector[index]); } } } int main(){ std::vector<double> vect = {1, 2, 3, 5, 9, 16, 21, 24}; applyFunction(vect, divisible_3, sqrt_wrap); // 传自定义包装函数的地址 for(auto&& i: vect){ std::cout << i << std::endl; } }
方案二:将applyFunction改为模板函数,支持任意可调用对象
这种方式更灵活,不需要依赖函数指针,直接传递lambda、仿函数等可调用对象,同时避免取标准库函数地址的问题:
#include <iostream> #include <vector> #include <cmath> bool divisible_3(double n){ return static_cast<int>(n) % 3 == 0; } // 模板版本的applyFunction,接受任意可调用对象 template<typename FilterFunc, typename CalcFunc> void applyFunction(std::vector<double>& vector, FilterFunc filterf, CalcFunc calc) { for(size_t index = 0; index < vector.size(); index++){ if(filterf(vector[index])){ vector[index] = calc(vector[index]); } } } int main(){ std::vector<double> vect = {1, 2, 3, 5, 9, 16, 21, 24}; // 用lambda封装std::sqrt,直接传递lambda即可 applyFunction(vect, divisible_3, [](double x) { return std::sqrt(x); }); for(auto&& i: vect){ std::cout << i << std::endl; } }
两种方案都能解决问题,方案二更符合现代C++的风格,扩展性更强,建议优先使用。
内容的提问来源于stack exchange,提问作者JosephGen
相关产品推荐
相关产品推荐

