遍历对象

1
2
3
for(auto &a : A){
cout << a << endl;
}

在 C++ 中, 这种范围 for 循环适用于符合以下条件的对象 A:

A 是一个标准容器或具有 begin() 和 end() 方法的对象

如果 A 是一个 STL 容器(如 std::vector, std::list, std::map 等),或者是自定义类型但提供了 begin() 和 end() 方法,那么可以直接使用范围 for 循环:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <vector>
#include <iostream>

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

for (auto &a : A) { // 遍历 vector
std::cout << a << " ";
}
return 0;
}

# 等效于:
for (auto it = A.begin(); it != A.end(); ++it) {
auto &a = *it;
}

A 是一个普通数组

C++11 开始,范围 for 也支持 C-style 数组

1
2
3
4
int A[] = {1, 2, 3, 4, 5};
for (auto &a : A) {
std::cout << a << " ";
}

A 是一个自定义类,但必须实现 begin() 和 end()

如果 A 是一个 自定义类,必须提供 begin() 和 end() 方法,且返回的是可迭代对象(通常是迭代器):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <vector>

class MyClass {
std::vector<int> data = {1, 2, 3, 4, 5};
public:
auto begin() { return data.begin(); }
auto end() { return data.end(); }
};

int main() {
MyClass A;
for (auto &a : A) { // 依赖自定义的 begin() 和 end()
std::cout << a << " ";
}
}

A 不是一个指针

如果 A 是一个指针,则不能直接用于 for(auto &a : A),因为指针本身并不是一个可迭代对象:

1
2
3
4
int* A = new int[5]{1, 2, 3, 4, 5};

// ❌ 错误,不能对指针使用 range-for
// for (auto &a : A) { std::cout << a << " "; }

但可以这样遍历:

1
2
3
4
for (int i = 0; i < 5; ++i) {
std::cout << A[i] << " ";
}
delete[] A;

总结
可以使用 for(auto &a : A){} 的情况
• A 是 STL 容器(如 vector,list,map 等)
• A 是 普通数组
• A 是 实现了 begin() 和 end() 的自定义类
不能直接使用的情况
• A 是 指针(但可以使用普通 for 循环)
• A 没有 begin() 和 end() 方法(如 POD 结构体)


容器插入对象

顺序容器(如 vectordequelist

  • push_back(value):在容器尾部添加元素(适用于 vectordequelist)。
  • push_front(value):在容器头部添加元素(适用于 dequelist)。
  • insert(pos, value):在指定迭代器 pos 位置插入元素(适用于 vectordequelist)。
  • emplace_back(value):在尾部原地构造元素,避免不必要的拷贝(适用于 vectordeque)。
  • emplace(pos, value):在指定位置原地构造元素(适用于 vectordequelist)。

关联容器(如 unordered_mapunordered_setmapset

  • insert(value):插入元素,若键已存在(对于 mapset),则不会覆盖原值。
  • emplace(value):类似 insert(),但直接在容器内部构造对象,避免额外拷贝。
  • operator[](适用于 mapunordered_map
    • M[key] = value;:如果 key 存在,则更新值;如果 key 不存在,则创建新键并赋值。
    • M[key].push_back(value);:适用于 unordered_map<int, vector<int>> 这种情况,直接向 vector 追加元素。

适用于 unordered_map<int, vector<int>> M 的插入方法

情况方法适用场景
插入新的 key-value 对M.insert({key, {value}});key 不存在时插入
直接赋值M[key] = {value};创建新 key 或覆盖旧值
vector 追加元素M[key].push_back(value);key 存在时向 vector 追加

容器中查找元素

顺序容器(如 vectordequelist

std::find 用于查找顺序容器中是否存在某个元素,返回一个迭代器:

  • 如果找到元素,返回指向该元素的迭代器。
  • 如果没有找到,返回 end() 迭代器。
1
2
3
4
5
6
7
8
9
10
#include <algorithm>  // std::find
#include <vector>

std::vector<int> v = {1, 2, 3, 4, 5};
auto it = std::find(v.begin(), v.end(), 3);
if (it != v.end()) {
std::cout << "Found: " << *it << std::endl;
} else {
std::cout << "Not Found" << std::endl;
}

关联容器(如 setmapunordered_mapunordered_set

  1. find() 用于查找元素并返回指向该元素的迭代器。如果元素不存在,返回容器的 end() 迭代器
    • unordered_mapunordered_set 中,find() 是基于哈希查找的,平均时间复杂度为 O(1)。
    • mapset 中,find() 是基于红黑树的,平均时间复杂度为 O(log n)。
1
2
3
4
5
6
7
8
9
#include <set>

std::set<int> s = {1, 2, 3, 4, 5};
auto it = s.find(3);
if (it != s.end()) {
std::cout << "Found: " << *it << std::endl;
} else {
std::cout << "Not Found" << std::endl;
}
  1. count() 用于检查容器中是否存在指定元素。它返回元素的个数(对于 setunordered_set,最大值是 1,因为元素唯一;对于 mapunordered_map,返回的是键值对的个数):
    • 对于 unordered_mapunordered_setcount() 的平均时间复杂度为 O(1)。
    • 对于 mapsetcount() 的时间复杂度为 O(log n)。
1
2
3
std::map<int, std::string> m = {{1, "one"}, {2, "two"}};
std::cout << "Count of key 1: " << m.count(1) << std::endl; // 输出 1
std::cout << "Count of key 3: " << m.count(3) << std::endl; // 输出 0

特定查找方法

  • operator[]mapunordered_map
    用于通过键直接访问元素。如果键不存在,会插入一个默认构造的元素(mapunordered_map 特有):
1
2
3
std::unordered_map<int, std::string> umap;
umap[1] = "one"; // 直接插入元素
std::cout << "Value for key 1: " << umap[1] << std::endl;

注意,operator[] 不会告诉你元素是否存在,它直接返回对应的值。


Lambda 表达式

基本语法

1
[capture-list](parameters) -> return_type { body }

各部分解释:

  • capture-list:捕获外部变量的列表
  • parameters:参数列表(可选)
  • return_type:返回类型(可选,通常由编译器推导)
  • body:函数体

捕获列表的不同形式

1
2
3
4
5
6
7
8
[]        // 不捕获任何外部变量
[=] // 以值方式捕获所有外部变量
[&] // 以引用方式捕获所有外部变量
[x, &y] // 以值方式捕获x,以引用方式捕获y
[=, &x] // 以值方式捕获所有外部变量,但x以引用方式捕获
[&, x] // 以引用方式捕获所有外部变量,但x以值方式捕获
[this] // 捕获this指针
[*this] // 捕获当前对象的副本(C++17)

常见用法示例

简单的Lambda函数

1
2
auto add = [](int a, int b) { return a + b; };
int sum = add(3, 4); // sum = 7

捕获外部变量

1
2
3
int multiplier = 10;
auto multiply = [multiplier](int x) { return x * multiplier; };
int result = multiply(5); // result = 50

修改捕获的值(使用mutable)

1
2
3
4
int counter = 0;
auto increment = [counter]() mutable { return ++counter; };
cout << increment(); // 输出1
cout << counter; // 输出0(原始counter不变)

捕获引用

1
2
3
4
int counter = 0;
auto increment = [&counter]() { return ++counter; };
cout << increment(); // 输出1
cout << counter; // 输出1(原始counter改变)

指定返回类型

1
auto divide = [](double a, double b) -> int { return a / b; };

进阶用法示例

Lambda作为函数参数

1
2
3
4
5
6
7
vector<int> nums = {1, 2, 3, 4, 5};

// 将lambda作为算法参数
sort(nums.begin(), nums.end(), [](int a, int b) { return a > b; });

// 使用lambda进行条件筛选
auto it = find_if(nums.begin(), nums.end(), [](int x) { return x > 3; });

泛型Lambda(C++14及以后)

1
2
3
4
// C++14泛型lambda
auto add = [](auto a, auto b) { return a + b; };
int sum1 = add(3, 4); // 整数加法
string sum2 = add(string("Hello, "), string("World")); // 字符串连接

Lambda自引用(C++20及以后)

1
2
3
4
5
6
// C++20自引用lambda
auto factorial = [](this auto&& self, int n) -> int {
if (n <= 1) return 1;
return n * self(n - 1);
};
int result = factorial(5); // 计算5! = 120

语法解释:

  • this auto&& self:声明lambda自身的参数
  • 使用self调用lambda本身,实现递归

Lambda模板(C++20)

1
2
3
4
auto print = []<typename T>(vector<T> const& v) {
for(auto const& element : v)
cout << element << ' ';
};

Lambda与STL结合使用

1
2
3
4
5
6
7
8
vector<int> v = {1, 2, 3, 4, 5};

// transform使用lambda
transform(v.begin(), v.end(), v.begin(), [](int x) { return x * x; });

// 自定义accumulate
int sum = accumulate(v.begin(), v.end(), 0,
[](int total, int current) { return total + current * 2; });

捕获初始化(C++14)

1
2
3
auto generator = [counter = 0]() mutable { return ++counter; };
cout << generator(); // 1
cout << generator(); // 2

总结

C++ Lambda表达式语法总结表

语法特性示例说明
基本语法[](int x) { return x*x; }最简单的lambda表达式定义
值捕获[x](int y) { return x+y; }以值方式捕获变量x
引用捕获[&x](int y) { x += y; }以引用方式捕获变量x
隐式值捕获[=](int y) { return val+y; }以值方式捕获所有使用的外部变量
隐式引用捕获[&](int y) { val += y; }以引用方式捕获所有使用的外部变量
混合捕获[=, &x](int y) { x = val+y; }默认值捕获,x以引用方式捕获
this捕获[this](){ this->value++; }捕获当前对象的this指针
mutable关键字[x](int y) mutable { x++; }允许修改值捕获的变量
返回类型[](int x) -> double { return x/2.0; }明确指定返回类型
泛型参数[](auto x) { return x*x; }使用auto实现泛型lambda
捕获初始化[sum = 0](int x) mutable { return sum += x; }在捕获列表中初始化变量
lambda模板[]<typename T>(T x) { return x; }将lambda定义为模板
lambda自引用[](this auto&& self, int n) { return n > 0 ? n * self(n-1) : 1; }lambda递归调用自身
捕获*this[*this]() { value++; }捕获当前对象的副本
捕获结构化绑定auto [a, b] = p; [a, b]() { return a+b; }捕获结构化绑定变量

常见应用场景

应用场景示例说明
STL算法sort(v.begin(), v.end(), [](int a, int b) { return a > b; });自定义排序规则
条件筛选auto it = find_if(v.begin(), v.end(), [](int x) { return x > 10; });查找符合条件的元素
转换操作transform(v1.begin(), v1.end(), v2.begin(), [](int x) { return x*x; });将元素进行转换
事件处理button.onClick([&](auto e) { handleClick(); });UI事件回调
线程/异步std::thread t([&]() { processData(); });线程函数
递归算法std::function<int(int)> fib = [&fib](int n) { return n <= 1 ? n : fib(n-1) + fib(n-2); };使用std::function实现递归
IIFE[](){ setup(); return getValue(); }()立即调用的lambda表达式