拼接小字符串与截取长字符串子串,哪种实现更高效?
问题描述
我有这样一个使用场景:一次性接收以分隔字符串形式传入的数据块,后续需要在多处使用这些数据,根据需求返回不同形式:有时要包含所有分隔符的完整字符串,有时要单个子串。注意:输入的子串数量有固定上限,最多不超过10个。
示例:
输入数据:
this is string 1- this is string 2- this is string 3
预期输出1(完整字符串):
this is string 1-this is string 2-this is string 3
预期输出2(单个子串):
this is string 1-
this is string 2-
this is string 3
我设计了三种实现思路,不确定哪种更高效。注意:对象仅创建一次,但生命周期内会被多次访问。
三种方案代码如下:
方案1:Msg1
class Msg1 { private: std::vector<std::string> strings; public: std::string getString() { // 返回拼接后的长字符串 } std::string getString(int index) { // 返回strings[index] } };
方案2:Msg2
class Msg2 { private: std::string string1; std::string string2; std::string string3; // ... 最多到string10 public: std::string getString() { // 返回string1 + string2 + string3 + ... + string10 } std::string getString(int index) { // switch(index) { // case 0: return string1; // case 1: return string2; // // ... // } } };
方案3:Msg3
class Msg3 { private: std::string longString; public: std::string getString() { // 返回longString } std::string getString(int index) { // 查找第index个'-'的位置 // 截取到下一个'-'或末尾的子串并返回 } };
请问这三种方案哪种实现更高效?
方案效率分析
方案1(Msg1)
- 初始化阶段:需要将输入长字符串分割为子串存入
vector,一次分割操作时间复杂度为O(L)(L为输入字符串总长度),空间开销为所有子串存储量加上vector的少量额外内存。 - 完整字符串访问:默认实现每次调用都要重新拼接子串,会触发多次内存分配与拷贝,频繁调用时累积开销极高。若优化为第一次调用时缓存拼接结果,后续直接返回,可将该操作开销降至O(1)。
- 单个子串访问:直接返回
vector对应元素,O(1)时间复杂度,访问速度极快。
方案2(Msg2)
- 初始化阶段:与Msg1类似,需将输入字符串分割到10个固定成员变量中,时间复杂度O(L),空间开销为10个独立
std::string的存储量,比Msg1略高但可忽略。 - 完整字符串访问:同样每次调用都要拼接10个字符串,未优化时频繁调用开销大。
- 单个子串访问:通过
switch分支直接返回对应成员变量,理论上O(1)且无vector边界检查开销(现代编译器优化后与Msg1差异极小),但扩展性差——子串数量上限调整时需修改类成员与switch逻辑。
方案3(Msg3)
- 初始化阶段:直接存储输入长字符串,无需分割,初始化速度最快(仅字符串拷贝,O(1)时间),空间开销最小。
- 完整字符串访问:直接返回原字符串,O(1)时间,是三种方案中最快的。
- 单个子串访问:每次调用都需从头遍历字符串查找分隔符,时间复杂度O(L),频繁访问单个子串时累积开销极大。
结论
选择方案需结合你的访问模式:
- 如果频繁访问完整字符串,很少获取单个子串:Msg3是最优选择,初始化与完整字符串访问开销均最小。
- 如果频繁获取单个子串,偶尔访问完整字符串:Msg1或Msg2更合适。Msg1扩展性更好,Msg2在子串访问上略优但代码冗余,建议优先选Msg1并优化
getString()方法,缓存第一次拼接的结果。 - 如果两种访问都很频繁:优化后的Msg1是最佳选择——初始化时分割子串,第一次调用完整字符串时缓存结果,后续两种访问均为O(1)时间复杂度,兼顾效率与灵活性。
内容的提问来源于stack exchange,提问作者Sakht Londa
相关产品推荐
相关产品推荐

