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 会反映原数据的变化
}
相关推荐
库玛西18 分钟前
深入浅出传输层:UDP 与 TCP 协议全景指南
linux·服务器·网络·c++·笔记·tcp/ip·udp
Chester_19996 小时前
CSP202203C.计算资源调度器
开发语言·数据结构·c++·蓝桥杯
EXI-小洲7 小时前
Java 操作 Word:字符串替换、图片插入、动态生成表格与API接口下载
java·开发语言·spring boot·word
会周易的程序员8 小时前
给 PLC 写一个字节码虚拟机:STVM 虚拟机架构设计
开发语言·c++·虚拟机·软plc·iec61131·stvm
机器视觉知识推荐、就业指导8 小时前
为什么老说“纯 Qt 没啥就业市场”?
开发语言·qt
telepan8 小时前
Qt 开发避坑与性能指南:如何优雅、安全地定义全局常量字符串?
开发语言·qt
小灰灰搞电子8 小时前
完全驾驭 Qt 与数据库:C++ ORM 框架 QxOrm 原理与实践指南
数据库·c++·qt
QT界面美化性能优化8 小时前
QT+AI:使用AI技术为QT应用程序赋能
c++·人工智能·qt·opencv·qt教程·qt6.3
m0_695251498 小时前
Qt MaintenanceTool 使用国内镜像加速下载(超详细教程)
开发语言·qt
大衛說9 小时前
《Python 从入门到精通》系列总览与学习路线
开发语言·python·学习