最简实现是用std::stringstream配合>>操作符,它天然跳过连续空格、首尾空格及所有空白符,自动过滤空字符串,无需额外判断,结果为{"hello","world","test"}。

用 std::stringstream 最简实现,但要注意连续空格和首尾空格
直接用 std::stringstream 配合 operator>> 是最常用也最省心的方式——它天然跳过所有空白字符(包括多个空格、制表符、换行),且不产生空字符串。
示例:
std::string s = " hello world test ";
std::vector<:string> tokens;
std::stringstream ss(s);
std::string token;
while (ss >> token) {
tokens.push_back(token);
}
// tokens == {"hello", "world", "test"}
</:string>
注意:operator>> 按空白分隔并自动 trim,所以无需额外过滤。但这也意味着它无法区分空格与制表符/换行,如果输入含混合空白且需统一处理,这反而是优点。
需要保留分隔符语义?改用 std::string_view + 手动切分
当必须严格按空格(仅 ASCII space ' ')拆分,且想显式控制“哪些空格算分隔、哪些算内容”时,std::stringstream 就不够用了。比如字符串 "a b"(两个空格),你可能希望得到 {"a", "", "b"},但 stringstream 会跳过中间的空串。
此时推荐用 std::string_view 遍历 + find_first_not_of/find_first_of 组合:
std::vector<:string> split_by_space(const std::string& s) {
std::vector<:string> res;
size_t start = 0;
while (start start) { // 非空子串
res.emplace_back(s.substr(start, end - start));
}
start = end + 1;
}
return res;
}
</:string></:string>
这个版本只认空格字符,且保留连续空格产生的空项——如果你后续要手动过滤,加个 if (!token.empty()) 即可。
用 std::regex 拆分?性能差、易出错,除非真要正则逻辑
有人第一反应是 std::regex,比如 std::regex(" +") 去匹配空格序列。但实际中几乎没必要:
-
std::regex构造开销大,对简单空格拆分属于杀鸡用牛刀 - 默认
std::sregex_iterator行为容易误解:它返回的是匹配到的分隔符,不是分割后的片段,需额外处理边界 - Windows 下 MSVC 的
std::regex实现长期有 bug,GCC/Clang 也非零开销
真要用正则,至少写成:std::regex re("\s+")(匹配任意空白),再用 std::sregex_token_iterator 并传入 -1 参数取非匹配部分——但这又回到了 stringstream 能干的事,还更慢。
第三方库如 absl::StrSplit 或 boost::algorithm::split 怎么选?
如果项目已引入 absl,absl::StrSplit(s, ' ', absl::SkipEmpty()) 是最清晰的写法,语义明确、零拷贝(返回 string_view)、自动过滤空项。
而 boost::algorithm::split 默认保留空项,要过滤得手动传 boost::algorithm::token_compress_on,否则 "a b" 会得到 {"a", "", "b"}。
没引入外部依赖时,别为了一个 split 引入整个 Boost;有 absl 且团队统一用它,那就直接用——毕竟 absl::StrSplit 内部就是基于 string_view 手动扫描,既安全又高效。
真正容易被忽略的是:不同方法对 Unicode 空格(如 、 )完全不处理。C++ 标准库所有方案都只认 ASCII 空格或 isspace() 定义的窄字符空白。如果输入含 UTF-8 多字节空格,必须先做 Unicode-aware normalize,再拆分。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











