std::unique仅去除相邻重复元素,需先排序再调用unique+erase才能实现全局去重;对list可用成员函数unique自动擦除;自定义类型需提供比较逻辑;其性能优于set但要求数据有序或预处理。

std::unique 只能去重相邻重复元素
它不是“全容器去重”,而是把连续相同的元素压缩成一个,前提是数据已排序或本身相邻重复。直接对 std::vector{1,2,1,2} 调用 std::unique,结果仍是 {1,2,1,2}——因为没有相邻重复。
- 必须先调用
std::sort(若需全局去重),再用std::unique -
std::unique不改变容器大小,只把去重后的新尾部迭代器返回,需配合erase才真正删掉冗余元素 - 对
std::list可用成员函数unique(),它自动完成擦除,无需额外erase
正确写法:三步不能少——排序 + unique + erase
最常错在漏掉其中一步。比如只写 std::unique(v.begin(), v.end()),容器长度不变,末尾残留脏数据;或者忘了排序,导致逻辑去重失败。
- 对
std::vector/std::array:std::sort(v.begin(), v.end());<br>auto new_end = std::unique(v.begin(), v.end());<br>v.erase(new_end, v.end());
- 自定义类型需提供可比较的
operator<或传入比较函数,比如按id去重:std::unique(v.begin(), v.end(), [](const auto& a, const auto& b) { return a.id == b.id; }) - 注意:
std::unique的二元谓词判断的是“是否应被移除”,即当pred(*it, *(it-1))为 true 时,*it被视为重复项
std::unique 和 std::set/std::unordered_set 去重的区别
别为了去重盲目换容器。std::unique 是原地、O(n) 时间(排序另算)、不额外分配内存;而插入 std::set 是 O(n log n),std::unordered_set 平均 O(n) 但有哈希开销和内存占用。
- 要保序且已有排序?用
std::unique最轻量 - 不要求顺序,且原始数据杂乱无章?用
std::unordered_set构建新容器更快,代码也更直白 - 误用
std::set插入再转回 vector,会多一次拷贝+排序,纯属加戏
常见报错:invalid iterator 或值没变
典型现象是运行时崩溃,或调用后容器内容看起来完全没变化。根本原因通常是迭代器失效或谓词逻辑反了。
立即学习“C++免费学习笔记(深入)”;
- 对
std::vector边遍历边erase(不用std::unique)会导致迭代器失效——这不是std::unique的问题,但新手常混在一起调试 - 谓词写成
a == b而非a.id == b.id,编译不过;写成a > b却没配std::sort的相同比较逻辑,结果不可预测 - 用
std::unique处理std::vector<std::string>时,空字符串和大小写敏感性容易被忽略,比如"A"和"a"永远不会被判定为重复











