引言

C++ 标准模板库(STL)提供了一系列功能丰富的容器,这些容器不仅封装了数据结构,还提供了大量成员函数用于操作数据。此外,STL 还包含许多与容器配合使用的非成员函数,它们扩展了容器的功能,使操作更加灵活。

一、通用成员函数

几乎所有 STL 容器都提供了一组基础的通用成员函数,用于获取容器信息、修改容器状态等。

1.1 基本信息函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <vector>
#include <list>

int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
std::list<std::string> lst = {"apple", "banana", "cherry"};

// 容器大小相关
std::cout << "vector大小: " << vec.size() << std::endl; // 元素数量
std::cout << "list为空? " << (lst.empty() ? "是" : "否") << std::endl; // 是否为空
std::cout << "vector最大容量: " << vec.max_size() << std::endl; // 理论最大元素数

// 容器内容操作
vec.clear(); // 清空容器
std::cout << "vector清空后大小: " << vec.size() << std::endl;

lst.resize(5, "grape"); // 调整大小,新增元素用"grape"填充
std::cout << "list调整大小后: " << lst.size() << std::endl;

return 0;
}

1.2 迭代器相关函数

所有容器都提供了获取迭代器的函数,用于遍历容器元素:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <set>

int main() {
std::set<int> s = {3, 1, 4, 1, 5, 9};

// 获取迭代器
auto it_begin = s.begin(); // 指向第一个元素的迭代器
auto it_end = s.end(); // 指向最后一个元素之后的迭代器
auto it_rbegin = s.rbegin(); // 指向最后一个元素的反向迭代器
auto it_rend = s.rend(); // 指向第一个元素之前的反向迭代器

// 常量迭代器(不能通过迭代器修改元素)
auto it_cbegin = s.cbegin(); // const_iterator
auto it_crend = s.crend(); // const_reverse_iterator

std::cout << "正向遍历: ";
for (auto it = it_begin; it != it_end; ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;

std::cout << "反向遍历: ";
for (auto it = it_rbegin; it != it_rend; ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;

return 0;
}

二、序列容器特有成员函数

序列容器(如vector、list、deque等)提供了一系列针对序列结构的特有函数。

2.1 元素访问函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <vector>
#include <deque>

int main() {
std::vector<int> vec = {10, 20, 30, 40, 50};
std::deque<std::string> dq = {"first", "second", "third"};

// 访问元素
std::cout << "vector第一个元素: " << vec.front() << std::endl; // 第一个元素
std::cout << "vector最后一个元素: " << vec.back() << std::endl; // 最后一个元素
std::cout << "vector[2]: " << vec[2] << std::endl; // 随机访问
std::cout << "vector.at(3): " << vec.at(3) << std::endl; // 带边界检查的访问

// 修改元素
vec.front() = 100;
vec.back() = 500;
dq[1] = "modified";

std::cout << "修改后vector: ";
for (int num : vec) {
std::cout << num << " ";
}
std::cout << std::endl;

return 0;
}

2.2 插入与删除函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <list>

int main() {
std::list<int> lst = {1, 2, 3};

// 插入元素
lst.push_back(4); // 在末尾插入
lst.push_front(0); // 在开头插入

auto it = lst.begin();
std::advance(it, 2); // 移动迭代器到第3个元素
lst.insert(it, 100); // 在迭代器位置插入

std::cout << "插入后: ";
for (int num : lst) {
std::cout << num << " ";
}
std::cout << std::endl;

// 删除元素
lst.pop_back(); // 删除末尾元素
lst.pop_front(); // 删除开头元素

auto it2 = lst.begin();
std::advance(it2, 1);
lst.erase(it2); // 删除迭代器指向的元素

std::cout << "删除后: ";
for (int num : lst) {
std::cout << num << " ";
}
std::cout << std::endl;

return 0;
}

2.3 vector 特有的容量管理函数

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

int main() {
std::vector<int> vec;

vec.reserve(100); // 预留存储空间,避免多次内存分配
std::cout << "容量: " << vec.capacity() << ", 大小: " << vec.size() << std::endl;

for (int i = 0; i < 20; ++i) {
vec.push_back(i);
}
std::cout << "容量: " << vec.capacity() << ", 大小: " << vec.size() << std::endl;

vec.shrink_to_fit(); // 减少容量以匹配大小
std::cout << "收缩后容量: " << vec.capacity() << ", 大小: " << vec.size() << std::endl;

return 0;
}

三、关联容器特有成员函数

关联容器(如set、map、multiset、multimap)提供了基于键的操作函数。

3.1 查找与计数函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <map>
#include <set>

int main() {
std::map<std::string, int> score = {
{"Alice", 90}, {"Bob", 85}, {"Charlie", 95}
};
std::multiset<int> nums = {3, 1, 4, 1, 5, 9, 2, 6, 5};

// map查找
auto it = score.find("Bob");
if (it != score.end()) {
std::cout << "Bob的分数: " << it->second << std::endl;
}

// 计数
std::cout << "multiset中5的个数: " << nums.count(5) << std::endl;

// 范围查找
auto range = nums.equal_range(5);
std::cout << "multiset中所有的5: ";
for (auto it = range.first; it != range.second; ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;

return 0;
}

3.2 插入与删除函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <set>
#include <map>

int main() {
std::set<int> s;
std::map<int, std::string> m;

// 插入元素
auto [it1, inserted1] = s.insert(5); // C++17返回pair<iterator, bool>
std::cout << "5是否插入成功? " << (inserted1 ? "是" : "否") << std::endl;

auto [it2, inserted2] = s.insert(5); // 重复插入
std::cout << "再次插入5是否成功? " << (inserted2 ? "是" : "否") << std::endl;

// map插入
m.insert({1, "one"});
m.insert(std::make_pair(2, "two"));

// 删除元素
size_t erased = s.erase(5); // 返回删除的元素个数
std::cout << "删除的元素个数: " << erased << std::endl;

return 0;
}

四、无序容器特有成员函数

无序容器(如unordered_set、unordered_map)提供了与哈希相关的特有函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <unordered_map>

int main() {
std::unordered_map<std::string, int> um = {
{"apple", 5}, {"banana", 3}, {"cherry", 7}
};

// 哈希桶相关操作
std::cout << "桶数量: " << um.bucket_count() << std::endl;
std::cout << "负载因子: " << um.load_factor() << std::endl;
std::cout << "最大负载因子: " << um.max_load_factor() << std::endl;

// 查找元素所在的桶
std::string key = "banana";
std::cout << key << "所在的桶: " << um.bucket(key) << std::endl;
std::cout << "该桶中的元素数量: " << um.bucket_size(um.bucket(key)) << std::endl;

// 重新哈希
um.rehash(20); // 设置桶数量至少为20
std::cout << "重新哈希后桶数量: " << um.bucket_count() << std::endl;

return 0;
}

五、容器相关的非成员函数

STL 提供了许多非成员函数,用于操作容器,这些函数通常比成员函数更通用。

5.1 比较函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <vector>
#include <algorithm> // 比较函数所在头文件

int main() {
std::vector<int> v1 = {1, 2, 3, 4};
std::vector<int> v2 = {1, 2, 3, 4};
std::vector<int> v3 = {1, 2, 3};

// 容器比较
if (v1 == v2) {
std::cout << "v1与v2相等" << std::endl;
}

if (v3 < v1) {
std::cout << "v3小于v1" << std::endl;
}

return 0;
}

5.2 交换函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <list>
#include <algorithm>

int main() {
std::list<int> a = {1, 2, 3};
std::list<int> b = {4, 5, 6};

std::cout << "交换前: ";
for (int num : a) std::cout << num << " ";
std::cout << "| ";
for (int num : b) std::cout << num << " ";
std::cout << std::endl;

// 交换两个容器内容
std::swap(a, b);

std::cout << "交换后: ";
for (int num : a) std::cout << num << " ";
std::cout << "| ";
for (int num : b) std::cout << num << " ";
std::cout << std::endl;

return 0;
}

5.3 迭代器辅助函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <vector>
#include <iterator> // 迭代器辅助函数

int main() {
std::vector<int> vec = {10, 20, 30, 40, 50};

// 计算迭代器距离
auto start = vec.begin();
auto end = vec.end();
std::cout << "容器长度: " << std::distance(start, end) << std::endl;

// 移动迭代器
auto it = vec.begin();
std::advance(it, 2); // 向前移动2个位置
std::cout << "移动后迭代器指向: " << *it << std::endl;

// 复制迭代器并移动
auto it2 = std::next(it); // it2指向it的下一个元素
auto it3 = std::prev(end); // it3指向end的前一个元素
std::cout << "*it2: " << *it2 << ", *it3: " << *it3 << std::endl;

return 0;
}

5.4 算法函数

虽然不属于容器成员函数,但 STL 算法常与容器配合使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <vector>
#include <algorithm> // 算法库

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

// 排序
std::sort(vec.begin(), vec.end());
std::cout << "排序后: ";
for (int num : vec) std::cout << num << " ";
std::cout << std::endl;

// 查找
int target = 5;
auto it = std::find(vec.begin(), vec.end(), target);
if (it != vec.end()) {
std::cout << "找到" << target << ",位置: " << std::distance(vec.begin(), it) << std::endl;
}

// 计数
int count = std::count(vec.begin(), vec.end(), 1);
std::cout << "1出现的次数: " << count << std::endl;

return 0;
}