1、std::string::npos是C++中std::string类定义的一个静态常量,通常用于表示“未找到”或“直到字符串结束”。
常见用途:
表示查找操作,但未找到结果
std::string str = "hello word"; size_t pos = str.find("xyz"); if(pos == std::string::npos) { //查到结尾,但未找到 }表示从某个位置开始,截取到字符串末尾
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++编程范式。
#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、懒加载的具体体现
#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; }与普通容器相比:
#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 会反映原数据的变化 }