从 .NET 到 C++:集合处理的思考
1. IEnumerable
与 List
的比较
在 .NET 中,IEnumerable
和 List
是两种常用的集合类型,它们有各自的适用场景:
IEnumerable<T>
:- 优点:惰性求值,仅在迭代时计算,适用于大数据集或流式数据处理。
- 缺点:不能进行索引访问,没有直接的添加或移除元素的方法。
List<T>
:- 优点:支持索引访问,具备丰富的修改集合的方法(如添加、移除元素)。
- 缺点:非惰性求值,可能会占用更多内存。
在返回集合时,使用 IEnumerable<T>
可以提高灵活性和性能,特别是当集合操作需要惰性求值时。List<T>
则适合需要频繁增删元素或需要随机访问的场景。
2. IEnumerable
与 IEnumerator
的区别
IEnumerable
:表示一个可以被枚举的集合,提供一个GetEnumerator
方法返回一个IEnumerator
。IEnumerator
:表示一个枚举器,用于遍历集合中的元素,具有MoveNext
、Reset
和Current
属性。
3. C++ 中的集合处理
在 C++ 中,虽然没有直接对应 IEnumerable
的接口,但通过标准库的容器和迭代器,可以实现类似的功能。
标准库容器和迭代器
C++ 标准库提供了丰富的容器类型(如 std::vector
、std::list
、std::set
等)和迭代器,这些容器和迭代器可以结合算法库来进行集合操作。
迭代器示例:
#include <vector>
#include <iostream>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
for(auto it = vec.begin(); it != vec.end(); ++it) {
std::cout << *it << std::endl;
}
return 0;
}
std::copy_if
和 std::transform
C++98 引入了 std::copy_if
和 std::transform
,它们在 C++11 及之后版本中仍然可用,能够实现条件性复制和元素变换。
std::copy_if
示例:
#include <vector>
#include <algorithm>
#include <iostream>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
std::vector<int> result;
std::copy_if(vec.begin(), vec.end(), std::back_inserter(result), [](int n) { return n % 2 == 0; });
for (int value : result) {
std::cout << value << std::endl;
}
return 0;
}
std::transform
示例:
#include <vector>
#include <algorithm>
#include <iostream>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
std::vector<int> result;
std::transform(vec.begin(), vec.end(), std::back_inserter(result), [](int n) { return n * n; });
for (int value : result) {
std::cout << value << std::endl;
}
return 0;
}
综合示例:std::copy_if
和 std::transform
结合
#include <vector>
#include <algorithm>
#include <iostream>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
std::vector<int> even_numbers;
std::vector<int> even_squares;
std::copy_if(vec.begin(), vec.end(), std::back_inserter(even_numbers), [](int n) { return n % 2 == 0; });
std::transform(even_numbers.begin(), even_numbers.end(), std::back_inserter(even_squares), [](int n) { return n * n; });
for (int value : even_squares) {
std::cout << value << std::endl;
}
return 0;
}
4. 现代化的集合处理:C++20 的 std::ranges
C++20 引入了 std::ranges
,为集合处理提供了类似于 LINQ 的功能。
示例代码:
#include <vector>
#include <iostream>
#include <ranges>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
auto even_squares = vec
| std::ranges::views::filter([](int n) { return n % 2 == 0; })
| std::ranges::views::transform([](int n) { return n * n; });
for (int value : even_squares) {
std::cout << value << std::endl;
}
return 0;
}
5. 第三方库:C++17 中的 Range-v3
和 Boost.Range
Range-v3
Range-v3
是 C++20 std::ranges
的主要灵感来源,可以在 C++14 和 C++17 中使用。
安装:
vcpkg install range-v3
示例代码:
#include <range/v3/all.hpp>
#include <vector>
#include <iostream>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
auto even_squares = vec
| ranges::views::filter([](int n) { return n % 2 == 0; })
| ranges::views::transform([](int n) { return n * n; });
for (int value : even_squares) {
std::cout << value << std::endl;
}
return 0;
}
Boost.Range
Boost.Range
提供了类似 Range-v3
的功能。
安装:
vcpkg install boost-range
示例代码:
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <vector>
#include <iostream>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
auto even_squares = vec
| boost::adaptors::filtered([](int n) { return n % 2 == 0; })
| boost::adaptors::transformed([](int n) { return n * n; });
for (int value : even_squares) {
std::cout << value << std::endl;
}
return 0;
}
无论是使用 C++20 的 std::ranges
,还是在 C++17 及更早版本中通过 Range-v3
和 Boost.Range
,C++ 提供了强大的工具来进行现代化的集合处理。同时,通过 std::copy_if
和 std::transform
等标准算法,C++11 及更早版本也可以实现高效的集合操作。了解并灵活应用这些工具,可以极大提高代码的可读性、简洁性和性能。