std::ranges、std::views和懒加载

1、std::string::npos是C++中std::string类定义的一个静态常量,通常用于表示"未找到"或"直到字符串结束"。

常见用途:

表示查找操作,但未找到结果

cpp 复制代码
std::string str = "hello word";
size_t pos = str.find("xyz");
if(pos == std::string::npos)
{
    //查到结尾,但未找到
}

表示从某个位置开始,截取到字符串末尾

cpp 复制代码
std::string str = "hello world";
std::string sub = str.substr(6,std::string::npos);
//表示从位置6开始,截取到字符串末尾

2、惰性视图:是一种优化程序性能的编程技术。它的核心理念是:把要做的工作记录下来,但不立即执行,等到需要结果的那一刻,才进行真正的计算。

3、C++20引入的Ranges库是标准库模板STL的一次重大升级,它通过"视图"和"管道符 |"提供了一种更现代、更强大、也更安全的数据处理方式。

核心概念,Ranges库建立在几个相互关联的核心概念之上:

(1)范围:一个可以遍历的元素序列的抽象。如标准容器库vector,list,array等都是范围

(2)视图:一个轻量级的、非持有的范围,它不会复制数据,而是对底层数据进行某种操作(如筛选、转换等)并提供一个"视图"。视图的计算是惰性的,即只有在需要时才计算,这为性能优化提供了巨大空间。

(3)范围适配器:返回视图的函数或对象。它们是构建数据处理管道的基本单元,通过管道符 | 进行组合,数据从左向右流动,逻辑清晰直观。

(4)管道符:用于组合视图的操作符。R | A | B的写法让数据处理像流水线一样易于理解。

Ranges库并非仅仅是语法糖,它代表了一种全新的、更函数式的C++编程范式。

cpp 复制代码
#include <string>
#include <vector>
#include <algorithm>
#include <ranges>
#include <iostream>
int main()
{
	std::string word = "apple";
	auto hasWord = [&word](const std::string& s) {return s.find(word) != std::string::npos;};
	std::vector<std::string> words = { "apple pie", "banana split", "apple tart", "cherry cobbler" };
	auto res = words | std::views::filter(hasWord);

	for (auto s : res)
	{
		std::cout << s << std::endl;
	}

	std::vector<int> input{0,1,2,3,4,5,6,7,8,9,10};
	std::vector<int> intermediate, output;
	std::copy_if(input.begin(), input.end(), std::back_inserter(intermediate), [](int i) {return i % 3 == 0; });
	std::transform(input.begin(), input.end(), std::back_inserter(output), [](const int i) {return i * i; });
	for (auto i : intermediate)
	{
		std::cout << i << " ";
	}
	std::cout << std::endl;
	for (auto i : output)
	{
		std::cout << i << " ";
	}
	std::cout << std::endl;

	auto output2 = input | std::views::filter([](const int i) {return i % 3 == 0; });
	auto output3 = input | std::views::transform([](const int i) {return i * i; });
	for (auto i : output2)
	{
		std::cout << i << " ";
	}
	std::cout << std::endl;
	for (auto i : output3)
	{
		std::cout << i << " ";
	}
	std::cout << std::endl;
	auto output4 = input | std::views::filter([](const int i) {return i % 3 == 0; }) | std::views::transform([](const int i) {return i * i; });
	std::cout << "------------------" << std::endl;
	for (auto i : output4)
	{
		std::cout << i << " ";
	}
	std::cout << std::endl;
	return 0;
}

4、管道的作用

左边:数据源(容器、范围)

右边:视图适配器

效果:将数据源"喂给"视图适配器处理

5、懒加载的具体体现

cpp 复制代码
#include <iostream>
#include <vector>
#include <string>
#include <ranges>

int main() {
    std::vector<std::string> words = { "apple pie", "banana split", "apple tart" };

    int filterCalls = 0;
    auto hasApple = [&filterCalls](const std::string& s) {
        filterCalls++;
        std::cout << "Filter checking: " << s << std::endl;
        return s.find("apple") != std::string::npos;
        };

    // 创建视图 - 不会触发任何过滤检查
    auto view = words | std::views::filter(hasApple);
    std::cout << "After view creation, filter calls: " << filterCalls << std::endl;

    // 第一次遍历 - 触发过滤
    std::cout << "\nFirst iteration:\n";
    for (const auto& s : view) {
        std::cout << "  Result: " << s << std::endl;
    }
    std::cout << "Filter calls after first iteration: " << filterCalls << std::endl;

    // 第二次遍历 - 再次触发过滤
    std::cout << "\nSecond iteration:\n";
    for (const auto& s : view) {
        std::cout << "  Result: " << s << std::endl;
    }
    std::cout << "Filter calls after second iteration: " << filterCalls << std::endl;
}

与普通容器相比:

cpp 复制代码
#include <iostream>
#include <vector>
#include <string>
#include <ranges>

int main() {
    std::vector<std::string> words = {"apple pie", "banana split", "apple tart"};
    
    // 方式1:立即求值的传统方式
    auto hasApple = [](const std::string& s) {
        return s.find("apple") != std::string::npos;
    };
    
    std::vector<std::string> eager_result;
    std::copy_if(words.begin(), words.end(), 
                 std::back_inserter(eager_result), 
                 hasApple);
    // eager_result 现在就包含了所有匹配的字符串(副本)
    
    // 方式2:惰性求值的视图方式
    auto lazy_view = words | std::views::filter(hasApple);
    // lazy_view 不包含数据,只是知道如何过滤
    
    // 主要区别:
    // 1. 内存:eager_result 占用额外内存,lazy_view 不占用
    // 2. 时间:eager_result 立即计算,lazy_view 延迟计算
    // 3. 原数据修改:lazy_view 会反映原数据的变化
}
相关推荐
柒星栈38 分钟前
PHP 源码怎么加密防破解?三套方案实战指南
开发语言·php·android studio
勉灬之1 小时前
Next.js + Prisma 跨平台部署踩坑记
开发语言·javascript·ecmascript
这是个栗子1 小时前
前端开发中的常用工具函数(九)
开发语言·javascript·ecmascript·at
啦啦啦啦啦zzzz1 小时前
算法:回溯算法
c++·算法·leetcode
蓝创工坊Blue Foundry1 小时前
图片文字提取到 Excel:批量任务如何先定义要交付的字段
运维·服务器·开发语言·数据库·自动化·ocr·excel
会飞的小新1 小时前
C 标准库之 <fenv.h> 详解与深度解析
c语言·开发语言·microsoft
Lzg_na1 小时前
订阅发布模块事例
c++
郝学胜-神的一滴2 小时前
[简化版 GAMES 104] 现代游戏引擎 02:拆解现代游戏引擎5+1层级架构,吃透引擎底层核心逻辑
c++·unity·架构·游戏引擎·图形渲染·unreal engine·系统设计
汉克老师2 小时前
2026年CSP-J初赛分数线-----预测
c++·csp-j·小学生·学c++编程
脱胎换骨-军哥2 小时前
C++数据库存储引擎内核开发:B+树索引与MVCC并发控制的完整实现
数据库·c++·b树