for_each用于执行带副作用的操作并可返回有状态函数对象,transform则用于数据转换生成新序列;前者侧重操作,后者专注映射。

C++ STL中的
for_each
transform
for_each
transform
深入探讨
for_each
transform
std::for_each
for_each
for_each(InputIt first, InputIt last, UnaryFunction f)
first
last
f
立即学习“C++免费学习笔记(深入)”;
这个算法的特点在于,它返回的是传入的那个函数对象
f
for_each
在我看来,
for_each
for_each
#include <iostream>
#include <vector>
#include <algorithm> // for_each
#include <numeric> // iota
struct Summation {
int total = 0;
void operator()(int n) {
total += n;
}
};
int main() {
std::vector<int> numbers(5);
std::iota(numbers.begin(), numbers.end(), 1); // numbers: 1, 2, 3, 4, 5
// 示例1: 使用lambda打印元素
std::cout << "Elements: ";
std::for_each(numbers.begin(), numbers.end(), [](int n) {
std::cout << n << " ";
});
std::cout << std::endl;
// 示例2: 使用函数对象累加元素
Summation s = std::for_each(numbers.begin(), numbers.end(), Summation{});
std::cout << "Sum: " << s.total << std::endl; // 输出 15
// 示例3: 修改元素(通过引用捕获)
std::vector<int> mod_numbers = {10, 20, 30};
std::for_each(mod_numbers.begin(), mod_numbers.end(), [](int& n) {
n *= 2; // 将每个元素翻倍
});
std::cout << "Modified numbers: ";
std::for_each(mod_numbers.begin(), mod_numbers.end(), [](int n) {
std::cout << n << " ";
});
std::cout << std::endl; // 输出 20 40 60
return 0;
}std::transform
transform
一元转换:
transform(InputIt first, InputIt last, OutputIt d_first, UnaryOperation unary_op)
[first, last)
unary_op
d_first
二元转换:
transform(InputIt1 first1, InputIt1 last1, InputIt2 first2, OutputIt d_first, BinaryOperation binary_op)
[first1, last1)
[first2, first2 + (last1 - first1))
binary_op
d_first
transform
transform
push_back
#include <iostream>
#include <vector>
#include <algorithm> // transform
#include <numeric> // iota
#include <iterator> // back_inserter
int main() {
std::vector<int> numbers(5);
std::iota(numbers.begin(), numbers.end(), 1); // numbers: 1, 2, 3, 4, 5
// 示例1: 一元转换,将每个元素平方,存储到新vector
std::vector<int> squares;
std::transform(numbers.begin(), numbers.end(),
std::back_inserter(squares), // 使用back_inserter动态添加元素
[](int n) { return n * n; });
std::cout << "Squares: ";
std::for_each(squares.begin(), squares.end(), [](int n) {
std::cout << n << " ";
});
std::cout << std::endl; // 输出 1 4 9 16 25
// 示例2: 二元转换,将两个vector对应元素相加
std::vector<int> vec1 = {1, 2, 3};
std::vector<int> vec2 = {10, 20, 30};
std::vector<int> sums;
std::transform(vec1.begin(), vec1.end(),
vec2.begin(), // 第二个输入范围的起始
std::back_inserter(sums),
[](int a, int b) { return a + b; });
std::cout << "Sums: ";
std::for_each(sums.begin(), sums.end(), [](int n) {
std::cout << n << " ";
});
std::cout << std::endl; // 输出 11 22 33
// 示例3: 原地转换 (将所有元素翻倍)
std::vector<int> original_numbers = {1, 2, 3, 4, 5};
std::transform(original_numbers.begin(), original_numbers.end(),
original_numbers.begin(), // 输出范围与输入范围相同
[](int n) { return n * 2; });
std::cout << "Doubled numbers (in-place): ";
std::for_each(original_numbers.begin(), original_numbers.end(), [](int n) {
std::cout << n << " ";
});
std::cout << std::endl; // 输出 2 4 6 8 10
return 0;
}for_each
transform
在实际项目中,选择
for_each
transform
如果你只是想遍历容器,对每个元素执行一些操作,比如打印、日志记录、触发一个事件,或者通过引用修改元素,但并不打算创建一个新的容器来存储结果,那么
for_each
for_each
for_each
for_each
反之,如果你需要根据现有数据生成一个新的数据集,或者将现有数据按照某种规则进行映射和转换,那么
transform
transform
transform
我个人经验是,当我不确定时,会先问自己:这个操作会产生一个新的集合吗?如果答案是肯定的,那多半是
transform
for_each
for_each
push_back
transform
transform
for_each
transform
在使用
for_each
transform
首先,for_each
for_each
mutable
// 陷阱示例:for_each返回值的误解
int count = 0;
std::vector<int> data = {1, 2, 3};
// 错误示范:以为这里的count会被修改
std::for_each(data.begin(), data.end(), [&](int n) {
if (n % 2 == 1) {
count++; // 这里的count是lambda内部的副本,外部的count不会变
}
});
std::cout << "Count (incorrect): " << count << std::endl; // 仍然是0
// 正确做法:返回并使用lambda副本
auto counter_lambda = [c = 0](int n) mutable { // c按值捕获,mutable允许修改
if (n % 2 == 1) {
c++;
}
return c; // 返回c,但for_each返回的是整个lambda对象
};
auto result_lambda = std::for_each(data.begin(), data.end(), counter_lambda);
// 假设lambda可以访问其内部状态,但标准库lambda没有直接访问成员的接口
// 更好的方法是使用一个函数对象或一个带有引用捕获的lambda
struct OddCounter {
int count = 0;
void operator()(int n) {
if (n % 2 == 1) {
count++;
}
}
};
OddCounter oc = std::for_each(data.begin(), data.end(), OddCounter{});
std::cout << "Count (correct with functor): " << oc.count << std::endl; // 输出 2其次,对于
transform
std::back_inserter
std::front_inserter
std::inserter
std::vector<int>::begin()
resize
// 陷阱示例:transform输出范围管理
std::vector<int> source = {1, 2, 3};
std::vector<int> dest; // dest是空的
// 错误示范:直接传入dest.begin(),dest没有分配空间
// std::transform(source.begin(), source.end(), dest.begin(), [](int n){ return n*2; }); // 运行时错误!
// 正确做法1: 预先resize
std::vector<int> dest_resized(source.size());
std::transform(source.begin(), source.end(), dest_resized.begin(), [](int n){ return n*2; });
// 正确做法2: 使用back_inserter
std::vector<int> dest_inserter;
std::transform(source.begin(), source.end(), std::back_inserter(dest_inserter), [](int n){ return n*2; });性能考量方面,对于绝大多数场景,
for_each
transform
然而,在原地transform
f(x) = x + previous_element_value
transform
previous_element_value
最后,当处理大规模数据时,考虑C++17引入的并行执行策略。这些策略可以与
for_each
transform
for_each
transform
C++11及后续标准引入的特性,特别是Lambda表达式、范围for循环以及C++17的并行算法,极大地增强了
for_each
transform
Lambda表达式(C++11)
Lambda表达式无疑是
for_each
transform
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
int factor = 10;
// 使用Lambda结合for_each打印并访问外部变量
std::cout << "Using for_each with lambda: ";
std::for_each(numbers.begin(), numbers.end(), [&](int n) {
std::cout << n * factor << " "; // 捕获factor
});
std::cout << std::endl; // 输出 10 20 30 40 50
// 使用Lambda结合transform进行转换
std::vector<int> transformed_numbers;
std::transform(numbers.begin(), numbers.以上就是C++STL算法for_each和transform使用方法的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号