std::getline配合std::set是最简可行方案,逐行读取并插入自动排序去重;避免vector中转或stringstream拆分;禁用std::string_view以防悬空;大数据量时vector+sort更高效。

std::getline 配合 std::set<:string> 是最简可行方案
直接用 std::getline 逐行读取,插入 std::set 即可自动排序,无需后续调用 std::sort。关键在于避免先存入 std::vector 再转容器——那会多一次遍历和内存拷贝。
常见错误是把整段字符串用 std::stringstream 拆成 token 后再塞进 std::set,这会误判换行符(比如把 "a\nb" 当作一个 token),且破坏“按行”语义。
实操建议:
- 用
std::istringstream或文件流(std::ifstream)配合std::getline,每次提取完整一行(不含\n) - 每行调用
my_set.insert(line),std::set的红黑树特性保证 O(log n) 插入 + 自动去重 + 排序 - 若需保留重复行,改用
std::multiset;若需稳定迭代顺序且不关心键值分离,std::vector+std::sort更快但非有序容器
std::string_view + std::set 不可行,别踩这个坑
std::string_view 看似能避免拷贝,但 std::set 要求元素生命周期长于容器本身。而 std::getline 写入的临时 std::string 在循环末尾就销毁了,存进去的 string_view 或裸指针立刻悬空。
错误写法示例:
std::set<:string_view> lines;
std::string line;
while (std::getline(in, line)) {
lines.insert(line); // line 析构后,set 中的 view 失效
}</:string_view>
正确做法只有两种:
- 存完整
std::string(推荐,现代 C++ 移动语义下开销极小) - 用
std::vector<:string></:string>预分配容量 +reserve(),再统一插入std::set(仅当已知行数且内存敏感时考虑)
性能敏感场景:用 std::vector + std::sort 替代 std::set
如果输入行数超过 10⁴,std::set 的 log n 插入累积起来比单次 std::sort 更慢。实测在 10⁵ 行时,vector::push_back + std::sort 比 set::insert 快 2–3 倍,且内存局部性更好。
适用条件:
- 不需要边读边查(即不依赖
set::find实时查询) - 允许最终结果有序,但不强求容器本身是“有序关联容器”
- 行内容较短(std::vector<:string> 多次扩容
示例关键代码:
std::vector<:string> lines; lines.reserve(estimated_count); std::string line; while (std::getline(in, line)) lines.push_back(std::move(line)); std::sort(lines.begin(), lines.end());</:string>
需要自定义排序或忽略大小写?重载比较函数而非改容器
std::set 和 std::vector::sort 都支持传入比较器,不要试图手动维护 sorted vector 或用 map 模拟 set——逻辑复杂且易错。
例如忽略大小写排序:
- 对
std::set:定义struct CICompare { bool operator()(const std::string& a, const std::string& b) const; };,然后std::set<:string cicompare></:string> - 对
std::sort:传入 lambda:std::sort(lines.begin(), lines.end(), [](const auto&a, const auto&b) { return strcasecmp(a.c_str(), b.c_str())
注意 strcasecmp 非标准 C++,跨平台应改用 std::locale 或第三方库如 ICU;若只处理 ASCII,可手写小写转换比较。
真正容易被忽略的是:无论选 set 还是 vector+sort,只要行内含 null 字符(\0),std::getline 就无法正确分割——它停在第一个 \0 或换行符。此时必须用 std::istream::read 配合手动解析。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











