乐途乐途
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
  • C++ 学习路径
  • 第1章 C++概述与开发环境

    • C++ 语言概述与编译模型
    • 第一个 C++ 程序与规范
    • 开发环境配置
    • 预处理指令详解
  • 第2章 基本语法与类型系统

    • 变量与基本类型
    • 类型转换
    • 枚举类型
    • 引用与指针
    • 数组与 stdarray
    • 字符串与原始字符串字面量
    • const 与 constexpr
    • nullptr 与空指针
    • 类型推导 auto 与 decltype
    • 基于范围的 for 循环
    • 值类别全面解析
    • char16_t 与 char32_t
    • static_assert 编译期断言
  • 第3章 函数与重载

    • 函数声明与定义
    • 函数重载
    • 默认参数与内联函数
    • Lambda 表达式
    • 函数对象与 stdfunction
    • 后置返回类型与 noexcept
  • 第4章 类与对象

    • 类的基本定义
    • 构造函数与析构函数
    • 拷贝控制
    • 移动构造函数与移动赋值
    • 列表初始化与类内初始化器
    • 静态成员与嵌套类
    • 友元
    • =default 与 =delete
  • 第5章 继承与多态

    • 继承基础
    • 虚函数与多态
    • 虚函数表与动态绑定原理
    • 虚析构函数
    • 抽象类与纯虚函数
    • 多重继承与虚继承
    • 继承构造函数
  • 第6章 运算符重载

    • 运算符重载基础
    • 算术与关系运算符重载
    • 赋值与移动运算符重载
    • 特殊运算符重载
  • 第7章 模板与泛型编程

    • 函数模板
    • 类模板
    • 模板特化与偏特化
    • 可变参数模板
    • 别名模板与模板模板参数
    • SFINAE 与类型萃取
    • 依赖名与 typename/template 关键字
  • 第8章 异常处理

    • 异常处理机制
    • noexcept 与异常安全
    • RAII 与异常安全实践
  • 第9章 内存管理与智能指针

    • 动态内存与内存分区
    • RAII 惯用法
    • unique_ptr
    • shared_ptr 与 weak_ptr
    • 内存管理最佳实践
  • 第10章 右值引用与移动语义

    • 右值引用与值类别深度解析
    • std::move 原理与使用
    • 完美转发与 std::forward
    • 移动语义性能对比与最佳实践
  • 第11章 STL容器

    • vector 深度剖析
    • deque 内部机制
    • list 与 forward_list
    • map 与 set 深度解析
    • unordered 容器与哈希原理
    • array 与 tuple
    • 容器适配器
    • 容器选择全景指南
  • 第12章 STL算法与迭代器

    • 迭代器体系全解
    • 非变异算法
    • 变异算法
    • 排序与二分算法
    • Lambda 与算法组合
    • std::random 随机数库
    • 自定义迭代器开发
  • 第13章 IO流与文件

    • 标准 IO 流
    • 格式化输出控制
    • 文件流操作
    • 字符串流
    • std::regex 正则表达式
  • 第14章 并发与多线程

    • thread 基础与线程管理
    • mutex 与 lock_guard
    • unique_lock 与 condition_variable
    • thread_local 线程局部存储
    • atomic 与内存序
    • future 与 async 异步编程
    • std::chrono 时间库
  • 第15章 现代C++新特性

    • 从 C++11 到 C++20 演进路线
    • C++14 关键新特性
    • C++17 关键新特性
    • C++20 核心特性速览
  • 第16章 面试考点与最佳实践

    • C++ 综合最佳实践清单
    • 高频面试题精讲
    • 多线程面试题与实战
    • 内存管理常见陷阱与排查
  • 附录

    • C++ 核心知识点
    • C++ 专业术语

非变异算法

定义与作用

非变异算法(non-modifying algorithms)不修改容器中的元素,仅执行查找、计数、比较和遍历等只读操作。这些算法位于 <algorithm> 和 <numeric> 头文件中。

#include <algorithm>
#include <numeric>

std::vector<int> v{1, 3, 5, 7, 9};
auto it = std::find(v.begin(), v.end(), 5);     // 查找
auto n  = std::count(v.begin(), v.end(), 3);    // 计数

核心原理

常用非变异算法分类

完整示例

示例一:飞翔科技招聘筛选系统

场景说明:白歌用非变异算法为飞翔科技筛选候选人简历。

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

struct Candidate {
    std::string name;
    int score;
    int experience;  // 经验年限
    std::string skill;
};

void printCandidates(const std::string& title,
                     const std::vector<Candidate>& candidates) {
    std::cout << title << ":\n";
    for (const auto& c : candidates)
        std::cout << "  " << c.name << " | 分数:" << c.score
                  << " | 经验:" << c.experience << "年"
                  << " | 技能:" << c.skill << "\n";
}

int main() {
    std::vector<Candidate> pool = {
        {"大翔", 98, 8, "C++"},
        {"白歌", 95, 10, "架构设计"},
        {"小崔", 92, 5, "后端开发"},
        {"黄俪", 90, 4, "前端开发"},
        {"李眉", 88, 7, "运维"},
        {"孔蓝", 87, 5, "产品"},
        {"赵鸣", 85, 3, "运营"},
        {"孙鹤", 82, 1, "产品助理"},
    };

    // 1. find:精确查找
    auto it = std::find_if(pool.begin(), pool.end(),
        [](const Candidate& c) { return c.name == "白歌"; });
    if (it != pool.end())
        std::cout << "[find] 找到: " << it->name << ", 分数: " << it->score << "\n";

    // 2. count:统计
    int senior = std::count_if(pool.begin(), pool.end(),
        [](const Candidate& c) { return c.experience >= 5; });
    std::cout << "[count] 高级人才(>=5年): " << senior << " 人\n";

    // 3. search:子序列匹配
    std::vector<std::string> targetSkills{"C++", "架构设计"};
    // 查找连续两个候选人技能匹配 targetSkills
    auto searchIt = std::search(pool.begin(), pool.end(),
        targetSkills.begin(), targetSkills.end(),
        [](const Candidate& c, const std::string& skill) {
            return c.skill == skill;
        });
    if (searchIt != pool.end())
        std::cout << "[search] 技能序列匹配起点: " << searchIt->name << "\n";

    // 4. equal:比较两组数据
    std::vector<int> expectedScores{98, 95, 92, 90};
    std::vector<int> actualScores;
    for (const auto& c : pool) actualScores.push_back(c.score);

    bool scoresMatch = std::equal(expectedScores.begin(),
        expectedScores.end(), actualScores.begin());
    std::cout << "[equal] 分数匹配预期: " << std::boolalpha << scoresMatch << "\n";

    // 5. all_of / any_of / none_of
    bool allQualified = std::all_of(pool.begin(), pool.end(),
        [](const Candidate& c) { return c.score >= 80; });
    bool hasSenior = std::any_of(pool.begin(), pool.end(),
        [](const Candidate& c) { return c.experience >= 10; });

    std::cout << "[all_of] 全部 >= 80 分: " << allQualified << "\n";
    std::cout << "[any_of] 有经验 >= 10 年: " << hasSenior << "\n";

    // 6. minmax_element
    auto [minIt, maxIt] = std::minmax_element(pool.begin(), pool.end(),
        [](const Candidate& a, const Candidate& b) {
            return a.score < b.score;
        });
    std::cout << "[minmax] 最低: " << minIt->name << "(" << minIt->score
              << "), 最高: " << maxIt->name << "(" << maxIt->score << ")\n";
}

预期输出:

[find] 找到: 白歌, 分数: 95
[count] 高级人才(>=5年): 4 人
[search] 技能序列匹配起点: 大翔
[equal] 分数匹配预期: true
[all_of] 全部 >= 80 分: true
[any_of] 有经验 >= 10 年: true
[minmax] 最低: 孙鹤(82), 最高: 大翔(98)

逐段分析:

  • find_if 返回指向第一个满足谓词的元素,未找到返回 end()
  • count_if 统计满足谓词的元素数量
  • search 在序列中查找子序列(支持自定义比较器)
  • equal 比较两段区间是否完全相等
  • all_of/any_of/none_of(C++11)提供快捷的条件判断
  • minmax_element(C++11)一次遍历同时获取最小和最大值

示例二:for_each 日志审计

场景说明:李眉用 for_each 对飞翔科技运维日志批量标记审计信息。

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <iomanip>

struct LogEntry {
    std::string timestamp;
    std::string level;
    std::string message;
    bool audited = false;
};

int main() {
    std::vector<LogEntry> logs = {
        {"2026-06-14 09:00", "INFO",  "飞翔科技-服务启动"},
        {"2026-06-14 09:05", "WARN",  "飞翔科技-内存使用 85%"},
        {"2026-06-14 09:10", "ERROR", "飞翔科技-数据库连接超时"},
        {"2026-06-14 09:15", "INFO",  "飞翔科技-用户登录: 孔蓝"},
        {"2026-06-14 09:20", "ERROR", "飞翔科技-支付回调失败"},
    };

    int errorCount = 0;

    // for_each:遍历并执行操作(不修改容器,但可修改元素属性)
    std::for_each(logs.begin(), logs.end(),
        [&errorCount](LogEntry& entry) {
            entry.audited = true;

            if (entry.level == "ERROR") {
                ++errorCount;
                entry.message += " [需紧急处理]";
            } else if (entry.level == "WARN") {
                entry.message += " [关注]";
            }
        });

    std::cout << "=== 飞翔科技日志审计 ===\n";
    std::cout << "总共 " << logs.size() << " 条,ERROR " << errorCount << " 条\n\n";

    for (const auto& log : logs) {
        std::cout << log.timestamp << " [" << log.level << "] "
                  << log.message;
        std::cout << " (audited: " << log.audited << ")\n";
    }
}

预期输出:

=== 飞翔科技日志审计 ===
总共 5 条,ERROR 2 条

2026-06-14 09:00 [INFO] 飞翔科技-服务启动 (audited: true)
2026-06-14 09:05 [WARN] 飞翔科技-内存使用 85% [关注] (audited: true)
2026-06-14 09:10 [ERROR] 飞翔科技-数据库连接超时 [需紧急处理] (audited: true)
2026-06-14 09:15 [INFO] 飞翔科技-用户登录: 孔蓝 (audited: true)
2026-06-14 09:20 [ERROR] 飞翔科技-支付回调失败 [需紧急处理] (audited: true)

逐段分析:

  • for_each 对每个元素执行回调,可以修改元素属性(不修改容器结构)
  • Lambda 捕获 errorCount 引用,在遍历中累积统计
  • 相比原始 for 循环,for_each 语义更清晰——明确表达"对每个元素做某事"

易错场景与面试考点

易错场景

1. find 未找到时解引用

auto it = std::find(v.begin(), v.end(), 999);
// std::cout << *it;  // ❌ 如果 it == end(),解引用是未定义行为
if (it != v.end()) std::cout << *it;  // ✅

2. equal 第二区间必须至少和第一区间等长

std::vector<int> a{1, 2, 3, 4};
std::vector<int> b{1, 2};
// std::equal(a.begin(), a.end(), b.begin());  // ❌ b 不够长

3. minmax 参数类型一致

auto result = std::min(5, 3.14);  // ❌ 编译错误!int vs double
auto result2 = std::min<double>(5, 3.14);  // ✅ 显式指定类型

面试考点

考点要点
for_each vs range-forfor_each 可配合并行策略(C++17),语义明确
find vs binary_searchfind O(n),binary_search 需有序 O(log n)
search 复杂度O(n*m),最坏情况下的朴素匹配
equal vs mismatchequal 返回 bool,mismatch 返回差异位置
minmax_elementC++11,一次遍历比分别调用两次高效
all_of/any_of/none_ofC++11,空区间:all_of=true, any_of=false, none_of=true
上一页
迭代器体系全解
下一页
变异算法