C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > C++20 范围库

全面深入了解C++20 范围库(std::ranges)

作者:流星雨爱编程

C++20范围库(std::ranges)是对传统STL的重大升级,它解决了传统STL的繁琐写法、组合困难等问题,支持线性链式调用和惰性求值,感兴趣的可以了解一下

1.核心基础概念

C++20 正式引入范围库 (std::ranges),是对传统 STL 迭代器 + 算法体系的重大升级。它基于概念 (Concept)、范围 (Range)、视图 (View)、管道语法、投影 (Projection) 五大核心能力,解决了传统 STL 写法繁琐、组合困难、易产生临时对象等问题,实现线性链式调用、惰性求值、零开销视图。

1.1.范围 (std::ranges::range)

范围是满足 range 概念的类型:只要类型拥有合法的 begin() 和 end(),返回迭代器 / 哨兵,就是一个范围。

传统 STL 必须传 begin()/end(),Ranges 算法直接接收整个范围,写法大幅简化。

C++标准库之std::begin、std::end、std::pre和std::next

1.2.哨兵 (Sentinel)

C++20 哨兵 (Sentinel) 是范围库 (Ranges) 引入的核心概念之一,是对传统迭代器模型的重大泛化。它彻底改变了序列结束位置的表示方式,允许迭代器与结束标记类型不同,从而支持无界范围、自定义终止条件、优化边界判断等场景,为现代 C++ 序列处理提供了极大灵活性。

哨兵是标记范围 (Range) 结束位置的对象,满足 std::sentinel_for<I> 概念,其中 I 是对应的起始迭代器类型。它的核心作用是与迭代器进行相等性比较,判断遍历是否结束,而不必与迭代器是同一类型。

C++20 范围的定义:一个对象只要提供 begin()(返回迭代器)和 end()(返回哨兵),且满足 sentinel_for<decltype(end()), decltype(begin())>,就是合法的范围。

与传统迭代器的根本区别:

特性传统 STL 迭代器对C++20 迭代器 + 哨兵
类型要求begin() 和 end() 必须返回同类型迭代器end() 可返回任意类型哨兵,只要满足 sentinel_for 概念
结束判断迭代器相等比较迭代器与哨兵的自定义比较逻辑
适用场景有限、已知边界的序列有限 / 无限序列、自定义终止条件、输入流等
性能边界判断固定为指针比较可优化为更高效的判断逻辑(如直接检查值)

核心概念:sentinel_for 与 sized_sentinel_for:

简化示例:值边界哨兵

更简洁的哨兵实现,用于固定值边界判断:

#include <ranges>
#include <iostream>

// 边界哨兵:当迭代器值等于bound时终止
template <typename T>
struct BoundSentinel {
    T bound;
    // 比较函数:迭代器值 == 边界值时终止
    friend bool operator==(const auto& it, const BoundSentinel& sentinel) {
        return *it == sentinel.bound;
    }
    friend bool operator!=(const auto& it, const BoundSentinel& sentinel) {
        return !(it == sentinel);
    }
};

int main() {
    int arr[] = {1, 2, 3, 4, 5, 0, 6, 7}; // 0作为终止标记
    auto range = std::ranges::subrange(std::begin(arr), BoundSentinel<int>{0});
    
    for (int x : range) {
        std::cout << x << " "; // 输出 1 2 3 4 5
    }
    return 0;
}

1.3.视图 (std::ranges::view)

视图是 Ranges 最核心的组件,也是和普通范围最大的区别:

区分:范围 = 序列本身,视图 = 序列的 “透 视滤镜”。

1.4.借用范围 (borrowed_range)

用于保证临时范围可以被视图安全引用,避免悬垂引用。

例如 std::vector{1,2,3} | filter(...),临时容器生命周期会被视图合理托管。

1.5.管道语法|

Ranges 专属链式语法,格式:

原始范围 | 适配器1 | 适配器2 | 适配器3

等价于函数嵌套:适配器3(适配器2(适配器1(原始范围))),从左到右依次执行,代码线性可读。

2.std::ranges 整体分类

范围库全部位于 std::ranges 命名空间下,分为四大模块:

3.范围算法(std::ranges 算法)

3.1.语法差异

形式1:范围重载(推荐,日常首选)

传统 STL 算法:必须传递首尾迭代器

std::sort(vec.begin(), vec.end());

C++20 Ranges 算法:直接传入整个范围

// 模板原型
template <std::ranges::input_range R, ...>
void 算法名(R&& range, 其他参数...);

std::ranges::sort(vec);

形式2:迭代器 + 哨兵重载(兼容传统 / 自定义哨兵)

兼容旧式迭代器写法,同时原生支持迭代器与哨兵类型不同(C++20 哨兵特性),传统 STL 算法强制首尾迭代器同类型。

// 模板原型
template <std::input_iterator I, std::sentinel_for<I> S, ...>
void 算法名(I first, S last, 其他参数...);

// 示例:传统迭代器 + 标准哨兵
std::ranges::sort(vec.begin(), vec.end());
// 示例:迭代器 + 自定义哨兵(C字符串)
auto cstr = "hello";
std::ranges::for_each(cstr, std::default_sentinel, [](char c){});

3.2.核心增强:投影 (Projection)

投影是一个可调用对象,接收单个元素,返回参与算法逻辑的值,全程只读、不修改原数据。 专门用于提取结构体成员、计算衍生值,大幅简化结构体 /std::pair 的排序、查找、统计逻辑。

绝大多数 Ranges 算法新增投影参数,用于提取元素的成员 / 属性,替代繁琐的 Lambda,是高频用法。

语法规则(通用):        

std::ranges::算法(范围, 谓词, 投影函数);

三种主流写法:

1.成员函数指针(最常用,结构体优先)

struct Student { std::string name; int score; };
// 投影:提取 score 成员
std::ranges::sort(stus, std::ranges::less<>, &Student::score);

2.Lambda 表达式(自定义计算 / 复杂取值)

// 投影:取元素绝对值参与比较
std::ranges::sort(vec, std::ranges::less<>, [](int x){ return std::abs(x); });

3.普通函数 / 函数对象(逻辑复用)

核心特点:

3.3.算法详解

绝大多数范围算法遵循固定参数顺序,按功能分为 5 大类,记住规则就不用死记函数签名:

算法分类通用参数顺序代表算法
等值匹配类范围, 目标值, 投影 = std::identitycount / find / contains
谓词判断类范围, 谓词函数, 投影 = std::identityall_of / find_if / count_if
比较排序类范围, 比较器 = ranges::less<>, 投影 = std::identitysort / max_element / partition
复制 / 变换类源范围, 目标迭代器, [谓词/变换函数]copy / copy_if / transform
条件删除类(专属)容器, [目标值/谓词], 投影 = std::identityerase / erase_if

3.3.1.遍历 & 逻辑判断算法

纯只读操作,不修改原范围,用于遍历元素、批量判断整体条件。

1.std::ranges::for_each 遍历执行

对每个元素执行自定义操作,等价传统 std::for_each。

int main() {
    std::vector<int> vec = {1,2,3,4,5};

    // 基础遍历
    std::ranges::for_each(vec, [](int x){
        std::cout << x << " ";
    });
    return 0;
}

2.all_of / any_of / none_of 全局条件判断

struct Student {
    std::string name;
    int score;
};

int main() {
    std::vector<Student> stus = {{"A", 85}, {"B", 59}, {"C", 90}};

    // 投影取 score:判断是否全部及格(>=60)
    bool all_pass = std::ranges::all_of(stus, [](int s){ return s >= 60; }, &Student::score);
    // 判断是否存在满分
    bool has_full = std::ranges::any_of(stus, [](int s){ return s == 100; }, &Student::score);
    // 判断是否无人不及格
    bool no_fail = std::ranges::none_of(stus, [](int s){ return s < 60; }, &Student::score);

    std::cout << std::boolalpha << all_pass << " " << has_full << " " << no_fail;
    return 0;
}

3.3.2.查找算法

定位元素位置,全部返回 subrange,支持投影,分为正向查找、反向查找、存在性判断。

1.find / find_if / find_if_not 正向查找

int main() {
    std::vector<int> vec = {10,20,30,40,50};

    // 查找值为30的元素
    auto r1 = std::ranges::find(vec, 30);
    if (!r1.empty()) std::cout << "找到:" << *r1.begin() << "\n";

    // 查找第一个大于25的元素
    auto r2 = std::ranges::find_if(vec, [](int x){ return x > 25; });
    return 0;
}

2.find_last / find_last_if 反向查找(C++20 新增)

从尾部向前查找,传统 STL 需要手写反向迭代器,此处写法大幅简化。

std::vector<int> vec = {2, 1, 2, 3, 2};
auto last_two = std::ranges::find_last(vec, 2); // 最后一个 2

3.contains 存在性判断(极简接口)

直接返回 bool,判断范围是否包含目标值,无需判断迭代器 / 子范围。

std::vector<int> vec = {1,2,3,4};
bool has_3 = std::ranges::contains(vec, 3);  // true
bool has_9 = std::ranges::contains(vec, 9);  // false

3.3.3.计数算法

统计符合条件的元素数量,支持投影。

1.count 统计等值元素

统计等于目标值的元素个数。

2.count_if 统计条件元素

统计满足谓词的元素个数。

struct User {
    std::string name;
    int age;
};

int main() {
    std::vector<User> users = {{"Tom", 18}, {"Lily", 22}, {"Jack", 18}};

    // 投影 age:统计 18 岁人数
    int cnt18 = std::ranges::count(users, 18, &User::age);
    // 统计年龄 > 20 的人数
    int cntAdult = std::ranges::count_if(users, [](int a){ return a > 20; }, &User::age);

    std::cout << "18岁人数:" << cnt18 << "\n";
    return 0;
}

3.3.4.最值算法

查找最大 / 最小元素,返回 subrange;minmax_element 一次遍历同时获取最值,效率更高。

struct Player {
    std::string name;
    int level;
};

int main() {
    std::vector<Player> players = {{"P1", 10}, {"P2", 20}, {"P3", 15}};

    // 等级最高的玩家
    auto maxLv = std::ranges::max_element(players, std::ranges::less<>, &Player::level);
    // 同时获取最小、最大等级
    auto [minR, maxR] = std::ranges::minmax_element(players, std::ranges::less<>, &Player::level);

    std::cout << "最高等级:" << maxR->level;
    return 0;
}

3.3.5.排序 & 分区算法

原地修改范围顺序,投影在此类算法中价值最高,是工程最常用算法。

1.sort / stable_sort 排序

语法:sort(范围, 比较器 = ranges::less<>, 投影 = identity)

struct Goods {
    std::string name;
    double price;
    int stock;
};

int main() {
    std::vector<Goods> goods = {
        {"Apple", 5.5, 100},
        {"Banana", 3.2, 200},
        {"Orange", 4.0, 80}
    };

    // 1. 按价格【升序】(默认 less<>)
    std::ranges::sort(goods, std::ranges::less<>, &Goods::price);
    // 2. 按库存【降序】(使用 greater<>)
    std::ranges::sort(goods, std::ranges::greater<>, &Goods::stock);

    return 0;
}

2.partial_sort 局部排序

仅对前 N 个元素排序,剩余元素无序,适合「取 TopN」场景,性能优于全排序。

std::vector<int> vec = {5,3,9,1,7,2};
// 只排序前 3 个元素
std::ranges::partial_sort(vec, vec.begin() + 3);
// 结果:1 2 3 | 9 7 5(后半段无序)

3.nth_element 第 N 元素定位

将第 N 个位置放置全局第 N 小元素,左侧都 ≤ 它,右侧都 ≥ 它,两侧无序。常用于快速取中位数、TopK。

std::vector<int> vec = {9,5,1,7,3};
// 让第2个位置(下标2)为全局第3小元素
std::ranges::nth_element(vec, vec.begin() + 2);

4.partition / stable_partition 分区

按条件将范围分为两部分:满足条件在前,不满足在后。

std::vector<int> vec = {1,2,3,4,5,6};
// 偶数放前面,奇数放后面
std::ranges::partition(vec, [](int x){ return x % 2 == 0; });

3.3.6.二分查找算法(要求范围必须升序有序)

基于二分查找,时间复杂度 (O(log N)),无序范围使用会导致未定义行为。

算法功能返回值
binary_search判断元素是否存在bool
lower_bound第一个 ≥ 目标值 的位置subrange
upper_bound第一个 > 目标值 的位置subrange
equal_range所有等于目标值的连续区间subrange
int main() {
    std::vector<int> vec = {1,2,3,4,5,6}; // 必须有序

    bool exist = std::ranges::binary_search(vec, 4); // true
    auto left  = std::ranges::lower_bound(vec, 3);
    auto right = std::ranges::upper_bound(vec, 3);
    auto eqRange = std::ranges::equal_range(vec, 3);

    return 0;
}

3.3.7.反转、旋转、相邻去重(原地修改)

1.reverse 原地反转

std::vector<int> vec = {1,2,3};
std::ranges::reverse(vec); // 原地变为 {3,2,1}

2.rotate 序列旋转

以指定迭代器为新起点,循环平移整个序列。

std::vector<int> vec = {1,2,3,4,5};
// 从第3个元素开始旋转 → 3 4 5 1 2
std::ranges::rotate(vec, vec.begin() + 2);

3.unique 相邻去重

仅删除相邻重复元素(和传统行为一致),重复元素会被移到尾部,通常配合 erase 彻底删除。

std::vector<int> vec = {1,1,2,2,3,3};
auto newEnd = std::ranges::unique(vec); // 去重,尾部残留重复值
vec.erase(newEnd.begin(), newEnd.end()); // 彻底清理

全局去重标准流程:sort → unique → erase

3.3.8.复制、变换、填充算法

用于元素拷贝、类型转换、批量赋值,常配合 std::back_inserter 动态扩容目标容器。

1.copy / copy_if 复制

std::vector<int> src = {1,2,3,4,5};
std::vector<int> dst;

// 复制所有偶数
std::ranges::copy_if(src, std::back_inserter(dst), [](int x){ return x%2 == 0; });

2.transform 元素变换

对每个元素执行映射转换,支持单范围和双范围重载。

std::vector<int> src = {1,2,3};
std::vector<int> dst;

// 所有元素 *2 后复制
std::ranges::transform(src, std::back_inserter(dst), [](int x){ return x * 2; });

3.fill / generate 批量填充

std::vector<int> vec(5);
std::ranges::fill(vec, 0);                // 全部填 0
std::ranges::generate(vec, [](){         // 生成 1,2,3,4,5
    static int n = 1;
    return n++;
});

3.3.9.元素删除算法(C++20 重磅优化)

彻底淘汰传统 erase + remove 老旧范式,一键删除,代码极简。

1.std::ranges::erase 删除指定值

删除容器中所有等于目标值的元素,直接修改容器。

std::vector<int> vec = {2,1,2,3,2};
std::ranges::erase(vec, 2); // 删除所有 2 → {1,3}

2.std::ranges::erase_if 条件删除

删除所有满足谓词的元素,支持投影(结构体场景利器)。

struct User { std::string name; int age; };
std::vector<User> users = {{"U1", 16}, {"U2", 20}, {"U3", 15}};

// 投影 age:删除年龄 < 18 的用户
std::ranges::erase_if(users, [](int a){ return a < 18; }, &User::age);

对比传统写法(冗余且易错):

// 传统 STL 写法(已淘汰) vec.erase(std::remove(vec.begin(), vec.end(), 2), vec.end());

3.3.10.有序集合算法(两个输入范围都必须升序有序)

对两个有序范围做集合运算,结果输出到目标迭代器。

int main() {
    std::vector<int> a = {1,2,3,4};
    std::vector<int> b = {3,4,5,6};
    std::vector<int> res;

    // 求交集 {3,4}
    std::ranges::set_intersection(a, b, std::back_inserter(res));
    return 0;
}

4.视图适配器 & 视图工厂

视图是 Ranges 组合能力的核心,惰性求值、无临时内存分配,通过管道 | 链式组合。

4.1.常用视图适配器(C++20 标准)

1.std::ranges::filter 过滤

保留谓词返回 true 的元素。

std::vector<int> vec = {1,2,3,4,5,6};

// 过滤偶数
auto even_view = vec | std::ranges::filter([](int x) { return x % 2 == 0; });

for (int x : even_view) std::cout << x << " "; // 2 4 6

2.std::ranges::transform 元素变换

对每个元素执行映射转换。

// 所有元素 * 2
auto double_view = vec | std::ranges::transform([](int x) { return x * 2; });

3.take / take_while 截取前缀

// 取前3个元素
auto take3 = vec | std::ranges::take(3); // 1 2 3

// 取小于4的元素
auto take_less4 = vec | std::ranges::take_while([](int x){ return x < 4; });

4.drop / drop_while 跳过前缀

auto drop2 = vec | std::ranges::drop(2); // 3 4 5 6

5.reverse 逆序视图

仅改变遍历顺序,不修改原容器(和 std::ranges::reverse 算法区分)。

auto rev_view = vec | std::ranges::reverse;

6.keys / values 键值视图

专门用于 std::map、std::pair 序列,快速提取键 / 值。

#include <map>
std::map<std::string, int> mp = {{"a",1}, {"b",2}};

// 提取所有 key
auto keys = mp | std::ranges::keys;
// 提取所有 value
auto vals = mp | std::ranges::values;

7.split 分割范围

按分隔符拆分序列,返回范围的范围(二维视图),常配合 join 使用。

#include <string>
std::string str = "hello,world,cpp20";

// 按逗号分割
auto split_view = str | std::ranges::split(',');

8.join 扁平化嵌套范围

将二维 / 多层视图拍平为一维。

// 分割后扁平化遍历
for (auto sub : str | std::ranges::split(',') | std::ranges::join) {
    std::cout << sub;
}

9.unique 相邻去重视图

仅去除相邻重复元素(和 std::unique 行为一致)。

4.2.视图工厂(生成新范围)

1.std::ranges::iota 连续数列

生成递增整数序列,支持有限范围、无限范围。

// 有限范围:[0, 10)
auto nums = std::ranges::iota(0, 10);

// 无限范围:从0开始无限递增(必须搭配 take 截断)
auto inf_nums = std::ranges::iota(0) | std::ranges::take(5);

2.single_view / empty_view

4.3.链式管道组合

多适配器串联,一行实现复杂逻辑,全程无临时容器:

#include <iostream>
#include <vector>
#include <ranges>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    // 逻辑:过滤奇数 → 元素*3 → 跳过前2个 → 取前3个 → 逆序
    auto res_view = vec
        | std::ranges::filter([](int x) { return x % 2 == 1; })  // 奇数:1,3,5,7,9
        | std::ranges::transform([](int x) { return x * 3; })    // 3,9,15,21,27
        | std::ranges::drop(2)                                   // 15,21,27
        | std::ranges::take(3)
        | std::ranges::reverse;

    for (int x : res_view) {
        std::cout << x << " "; // 27 21 15
    }

    return 0;
}

5.std::ranges::subrange子范围

绝大多数查找 / 区间算法返回 subrange,它是轻量级范围包装器:

示例如下:

std::vector<int> vec = {1,2,3,4,5,6};
// 找到 3 之后的所有元素,再过滤偶数
auto sub = std::ranges::find(vec, 3);
for (int x : sub | std::ranges::filter([](int x){ return x%2==0; })) {
    std::cout << x << " "; // 4 6
}

6.C++20 Ranges vs 传统 STL 写法 对比

C++20 范围库(std::ranges)完全兼容传统 STL 算法语义,但在调用形式、语法简洁度、组合能力、运行效率、容错性上做了全面革新。

6.1.整体对比

对比维度传统 STL(C++11~C++17)C++20 std::ranges
调用参数强制传 begin() + end() 迭代器对支持直接传整个容器 / 范围,也兼容迭代器对
成员取值依赖 Lambda 内部取结构体 / 成员,代码臃肿原生支持投影 (Projection),一行指定字段
结束标记begin/end 迭代器必须同类型支持哨兵 (Sentinel),迭代器与结束标记可不同类型
多步组合多步处理必须创建临时容器存中间结果视图 (View) 惰性求值,无临时容器,管道 `` 链式串联
返回值查找类返回原始迭代器查找 / 区间类统一返回 std::ranges::subrange(可继续遍历 / 链式调用)
删除逻辑固定 erase + remove 嵌套范式,易错专用 erase/erase_if,一键删除,语法极简
代码风格嵌套多、模板长、重复代码多线性链式、声明式风格,逻辑从上到下一目了然
运行开销多步变换伴随容器拷贝 / 内存分配视图零拷贝、惰性执行,性能等价手写循环
边界判断手动比较迭代器,语义晦涩subrange.empty() 直观判空,哨兵封装终止逻辑

6.2.分场景代码对比

1.结构体(投影核心场景)

需求:判断学生是否全部及格(按 score 字段)

struct Student {
    std::string name;
    int score;
};

传统 STL 写法: Lambda 内部手动提取成员,元素多时代码冗余

std::vector<Student> stus = {{"A",85}, {"B",66}, {"C",92}};
bool all_pass = std::all_of(stus.begin(), stus.end(), [](const Student& s){
    return s.score >= 60; // 每次都要手动取成员
});

C++20 Ranges 写法: 使用投影直接指定成员指针,谓词只关心业务逻辑

std::vector<Student> stus = {{"A",85}, {"B",66}, {"C",92}};
// 投影 &Student::score:算法自动提取分数,谓词接收 int 类型
bool all_pass = std::ranges::all_of(stus, [](int s){
    return s >= 60;
}, &Student::score);

差异总结:结构体场景下,投影彻底简化成员取值逻辑,Lambda 职责更单一。

2.元素删除(经典 erase-remove 范式)

这是传统 STL 最易错、最繁琐的场景之一,C++20 做了彻底优化。

传统STL:

users.erase(std::remove_if(users.begin(), users.end(),
    [](const User& u){ return u.age < 18; }),
    users.end());

Ranges 写法(搭配投影)

// 投影 age,谓词直接接收年龄值
std::ranges::erase_if(users, [](int a){ return a < 18; }, &User::age);

3.多步序列流水线(过滤 + 变换 + 截取)

需求:从序列中 过滤奇数 → 元素 ×3 → 跳过前 2 个 → 取前 3 个

每一步都必须新建 vector 存储中间结果,多次内存分配 + 拷贝,性能损耗明显

int main() {
    std::vector<int> src = {1,2,3,4,5,6,7,8,9,10};

    // 第1步:过滤奇数(临时容器1)
    std::vector<int> temp1;
    std::copy_if(src.begin(), src.end(), std::back_inserter(temp1),
        [](int x){ return x % 2 == 1; });

    // 第2步:元素 *3(临时容器2)
    std::vector<int> temp2;
    std::transform(temp1.begin(), temp1.end(), std::back_inserter(temp2),
        [](int x){ return x * 3; });

    // 第3步:跳过前2个,取前3个(最终结果)
    std::vector<int> res;
    auto first = temp2.begin() + 2;
    auto last = first + 3;
    std::copy(first, last, std::back_inserter(res));

    // 遍历输出
    for (int x : res) std::cout << x << " ";
    return 0;
}

C++20 Ranges 视图 + 管道写法:

使用视图 (View) + 管道 | 链式组合,全程无临时容器、惰性求值,只有遍历瞬间才执行逻辑

int main() {
    std::vector<int> src = {1,2,3,4,5,6,7,8,9,10};

    // 链式流水线:从上到下顺序执行,无中间拷贝
    auto pipeline = src
        | std::ranges::filter([](int x){ return x % 2 == 1; })  // 过滤奇数
        | std::ranges::transform([](int x){ return x * 3; })     // 元素*3
        | std::ranges::drop(2)                                  // 跳过前2个
        | std::ranges::take(3);                                 // 取前3个

    // 仅遍历这一刻才执行所有逻辑
    for (int x : pipeline) std::cout << x << " ";
    return 0;
}

4.C 风格字符串(哨兵 Sentinel 典型应用)

需求:遍历 \0 结尾的 C 字符串

传统写法:手动循环判断结束符 \0,或依赖迭代器指针

const char* str = "Hello C++";
while (*str != '\0') {
    std::cout << *str;
    ++str;
}

Ranges 写法(结合默认哨兵 default_sentinel):

将 C 字符串包装为标准范围,哨兵自动识别 \0,无需手动判断终止条件

#include <ranges>
const char* str = "Hello C++";
auto str_range = std::ranges::subrange(str, std::default_sentinel);
std::ranges::for_each(str_range, [](char c){ std::cout << c; });

差异总结:哨兵抹平了 “原生指针序列” 和 “标准容器” 的遍历差异。

6.3.核心特性深度对比(底层能力差异)

1.投影 (Projection)

2. 哨兵 (Sentinel)

3. 视图 (View) 与 临时对象

4. 管道语法 |

5. 返回值 subrange

6.4.性能对比

一句话:Ranges 是语法糖 + 架构升级,不牺牲性能,只提升开发效率与代码质量。

7.迁移与使用建议

1.新项目

直接全面使用 std::ranges:

2.老项目逐步迁移

3.避坑要点

8.C++23 对 Ranges 的扩展(补充)

C++23 在 C++20 基础上新增大量实用适配器,进一步强化组合能力:

9.总结

到此这篇关于全面深入了解C++20 范围库(std::ranges)的文章就介绍到这了,更多相关C++20 范围库内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文