copy、fill、replace、unique —— 批量改写容器内容的通用算法。
把一段区间的元素逐个复制到另一个位置。目标位置需要预先分配好足够的空间——copy 不会自动帮目标容器扩容,只是简单地逐个赋值。
| 1 | vector<int> src = {1, 2, 3, 4, 5}; |
| 2 | vector<int> dst(5); // 目标容器需要预先分配空间 |
| 3 | copy(src.begin(), src.end(), dst.begin()); |
| 4 | // dst 变成 {1, 2, 3, 4, 5} |
dst 是一个空的 vector(没有预分配空间),直接 copy 会越界访问、导致未定义行为。正确做法是先 dst.resize(src.size()) 或者在定义时就给够大小,就像例子里 vector<int> dst(5) 那样。resize 多大,可以用 back_inserter:copy(src.begin(), src.end(), back_inserter(dst));。它会在每次需要写入元素时,自动帮你调用 dst.push_back(...),不需要提前分配任何空间,dst 甚至可以是空的。使用前需要 #include <iterator>。把指定区间内的全部元素都设为同一个值,可以填充整个容器,也可以只填充一部分。
| 1 | vector<int> v(5); |
| 2 | fill(v.begin(), v.end(), 42); |
| 3 | // v 变成 {42, 42, 42, 42, 42} |
| 4 | |
| 5 | // 填充前 3 个 |
| 6 | fill(v.begin(), v.begin() + 3, 7); |
| 7 | // v 变成 {7, 7, 7, 42, 42} |
vector 整体清零或者初始化成某个固定值时,fill 比手写 for 循环更简洁。如果只需要清零,memset(C 风格)也能做到,看起来速度上更占优势,但两者的适用范围不一样:fill 可以安全地用在任何类型的对象上(包括 string、结构体这类"非平凡"类型),而 memset 只能安全地用在 POD 类型(可以简单理解为"纯数据、没有额外逻辑"的类型,比如 int、double、由这些基础类型组成的简单结构体)上——对 string、vector 这类内部管理着动态内存的类型用 memset,会破坏它们内部的状态,是未定义行为,非常容易崩溃。拿不准的时候,优先用 fill,更通用也更安全。把区间内所有等于某个值的元素,统一替换成另一个值。
| 1 | vector<int> v = {1, 2, 3, 2, 4}; |
| 2 | replace(v.begin(), v.end(), 2, 99); |
| 3 | // v 变成 {1, 99, 3, 99, 4} |
replace_if,第三个参数换成一个返回 bool 的判断函数,比如 replace_if(v.begin(), v.end(), [](int x){ return x < 0; }, 0) 把所有负数替换成 0。fill、replace 这类"批量写入"的算法,适用于 vector、list、deque 等序列容器,因为这些容器里的元素本身是可以随便改的。但对于 set、map 这类关联容器就通常用不了——set 的元素本身就是"键",map 的键也不能直接改(会破坏内部排序结构),强行对它们用 fill/replace 要么编译不通过,要么产生未定义行为。unique 把连续重复的元素只保留第一个,多余的"挤"到区间末尾,并返回新的"有效末尾"位置——但它不会真正删除元素,容器大小不变,需要配合 erase 才能真正缩短容器。
unique 返回的迭代器指向新末尾(绿色区域之后),灰色虚线格子是残留的脏数据,必须用 erase 删掉才算真正去重完成。| 1 | vector<int> v = {1, 2, 2, 3, 3, 3, 4}; |
| 2 | // unique 把重复元素移到末尾,返回新末尾的迭代器 |
| 3 | auto new_end = unique(v.begin(), v.end()); |
| 4 | v.erase(new_end, v.end()); // 真正删除多余元素 |
| 5 | // v 变成 {1, 2, 3, 4} |
unique 只移除连续重复的元素。如果元素是分散的(比如 {1, 2, 1, 3, 1}),unique 不会把三个 1 都去掉——需要先 sort 再 unique,让相同的元素先挨在一起,才能正确去重。这是竞赛里"排序去重"的标准三连招:sort → unique → erase。