在STL算法中使用函数对象:copy_if筛选均值以下元素遇阻
我来帮你梳理下这个自定义函数对象的问题,以及怎么修正它来配合copy_if完成需求。
问题分析与修正方案
你的Lower_than_mean函数对象存在几个可以优化和修复的点,导致它可能无法正常配合copy_if工作:
- 不必要的vector存储:类里保存了整个输入vector
d1,但实际上你只需要计算并存储均值mean就够了。保存整个vector不仅浪费内存,还会带来不必要的拷贝开销,完全没必要。 - operator()的参数问题:你的
operator()用了double& x作为参数,但copy_if遍历原vector时,迭代器指向的元素可能是const的(比如原vector是const引用传递,或者迭代器是const_iterator时),非const引用会直接触发编译错误。应该改成const double& x或者直接传值double x。 - 空vector的边界情况:如果输入的vector是空的,
d1.size()为0,计算mean = sum / d1.size()会触发除以0的未定义行为,必须在构造函数里处理这种情况。
修正后的完整代码
#include <vector> #include <algorithm> #include <numeric> #include <iterator> #include <iostream> struct Lower_than_mean { private: double mean; public: // 构造函数只计算并存储均值,不再保存整个vector Lower_than_mean(const std::vector<double>& a) { if (a.empty()) { // 处理空vector的情况,可根据需求调整默认值 mean = 0.0; return; } double sum = std::accumulate(a.begin(), a.end(), 0.0); mean = sum / a.size(); } // 修改参数为const引用,同时将operator()设为const(函数对象不应修改内部状态) bool operator()(const double& x) const { return x < mean; } }; int main() { std::vector<double> vd{3.4, 5.6, 7.0, 3.0, 4.0, 5.0}; std::vector<double> target; // 使用copy_if,通过back_inserter向目标vector插入元素 std::copy_if(vd.begin(), vd.end(), std::back_inserter(target), Lower_than_mean(vd)); // 打印结果验证(原vector均值≈4.666,输出应为3.4 3.0 4.0) for (double num : target) { std::cout << num << " "; } return 0; }
额外优化:用Lambda替代自定义函数对象
其实对于这种简单场景,完全可以不用自定义类,直接用Lambda表达式更简洁,可读性也更强:
#include <vector> #include <algorithm> #include <numeric> #include <iterator> #include <iostream> int main() { std::vector<double> vd{3.4, 5.6, 7.0, 3.0, 4.0, 5.0}; std::vector<double> target; if (!vd.empty()) { double mean = std::accumulate(vd.begin(), vd.end(), 0.0) / vd.size(); std::copy_if(vd.begin(), vd.end(), std::back_inserter(target), [mean](const double& x) { return x < mean; }); } // 打印结果 for (double num : target) { std::cout << num << " "; } return 0; }
内容的提问来源于stack exchange,提问作者TosinAl
相关产品推荐
相关产品推荐

