std::unique仅移除相邻重复元素,不排序也不改变容器物理大小,需先sort再unique+erase才能全局去重,且返回新逻辑结尾迭代器而非删除数量。

std::unique\_c++ 只作用于相邻重复项,不自动排序也不改变容器大小
很多人误以为 std::unique 能像 Python 的 set() 那样直接去重,其实它只移除「连续重复」的元素,且不会真正删除——只是把重复项挪到末尾,返回一个新逻辑结尾迭代器。容器物理大小不变,必须配合 erase 才能真正收缩。
正确用法:必须先排序(如需全局去重),再调用 unique + erase 惯用法
若目标是去除所有重复(非仅相邻),得先保证相同元素挨着:std::sort 是前置条件。否则 std::unique 会漏掉间隔出现的重复项。
-
std::vector<int> v = {3,1,2,1,3,2};</int>→ 直接unique后仍是{3,1,2,1,3,2}(无相邻重复,什么也不删) - 先
std::sort(v.begin(), v.end())→ 得{1,1,2,2,3,3},再unique+erase才得{1,2,3}
unique 返回的是新逻辑结尾,不是被删元素个数
std::unique 返回的是「去重后有效范围的尾后迭代器」,不是整数计数。常见错误是忽略这个返回值,或误用为删除数量。
auto last = std::unique(v.begin(), v.end()); v.erase(last, v.end()); // ✅ 正确:擦除从 last 到原 end 的冗余部分 // v.erase(v.begin(), last); // ❌ 错!这会删掉前面的有效部分
注意迭代器失效与自定义比较函数的使用场景
std::unique 支持自定义二元谓词,比如按对象某个字段去重、忽略大小写字符串比较等。但要注意:谓词必须满足「等价关系」(自反、对称、传递),否则行为未定义。
立即学习“C++免费学习笔记(深入)”;
- 对
std::vector<:string></:string>忽略大小写去重:std::unique(v.begin(), v.end(), [](const auto& a, const auto& b) { return std::equal(a.begin(), a.end(), b.begin(), b.end(), [](char x, char y) { return std::tolower(x) == std::tolower(y); }); }) - 操作前确保容器支持随机访问或至少前向迭代器;
std::list更推荐用其成员函数unique(),避免额外拷贝











